Advertisement
beqa1923

Untitled

Aug 26th, 2019
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.91 KB | None | 0 0
  1. import base64
  2. import binascii
  3. import json
  4. import urllib2
  5. import logging
  6.  
  7. from hashlib import sha1
  8. from logging.handlers import TimedRotatingFileHandler
  9. from Crypto.Cipher import AES
  10.  
  11. '''main defines'''
  12. # Silk Prod
  13. #_KEY = binascii.a2b_hex("428f62982c5e1db32d1e9f3b66f75ba9973810eb60c1001e4e581b50cc879fc8")
  14. #_IV = binascii.a2b_hex("29e4c7dc1c6f8cebcf86a04f34725c8f")
  15. #PROVIDER = "silknet"
  16. #LICENSE_SERVER_URL = "https://license.widevine.com/cenc/getlicense"
  17. #ALLOWED_TRACK_TYPES = "SD_HD"
  18.  
  19. # silk Test
  20. _KEY = binascii.a2b_hex("a3dff872487bdc5c104aa12e90ec1fe40858f56fca8b7b6f1ecd561099993a8c")
  21. _IV = binascii.a2b_hex("73d395265dbcd512dc488e4a532cf00e")
  22. PROVIDER = "silknet"
  23. LICENSE_SERVER_URL = "https://license.uat.widevine.com/cenc/getlicense"
  24. ALLOWED_TRACK_TYPES = "SD_HD"
  25. ALLOW_UNVERIFIED_PLATFORM = True
  26.  
  27. PARSEFIRST = False
  28.  
  29. '''logger init'''
  30. log = logging.getLogger('proxy')
  31. log.setLevel(logging.DEBUG)
  32. aFormat = logging.Formatter('[%(asctime)s][%(levelname)s] %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
  33. consoleHandler = logging.StreamHandler()
  34. consoleHandler.setLevel(logging.DEBUG)
  35. consoleHandler.setFormatter(aFormat)
  36. fh = TimedRotatingFileHandler(filename = 'vwproxy.log', when='midnight')
  37. fh.setFormatter(aFormat)
  38. log.addHandler(fh)
  39. log.addHandler(consoleHandler)
  40.  
  41. '''functions'''
  42. def generateSignature(text_to_sign):
  43. """Ingest License Request and Encrypt"""
  44. try:
  45. hashed_text = sha1(text_to_sign).digest()
  46. cipher = AES.new(_KEY, AES.MODE_CBC, _IV)
  47. padding = binascii.a2b_hex("" if len(hashed_text) % 16 == 0
  48. else (16 -(len(hashed_text) % 16)) * "00")
  49. aes_msg = cipher.encrypt(hashed_text + padding)
  50. signature = base64.b64encode(aes_msg)
  51. return signature
  52. except Exception as e:
  53. log.error('error generating signature' + str(e))
  54. return -1
  55.  
  56. def sendRequest(message):
  57. """Send HTTP request via urllib2"""
  58. try:
  59. f = urllib2.urlopen(LICENSE_SERVER_URL + "/" + PROVIDER, message)
  60. return f.read()
  61. except urllib2.HTTPError as e:
  62. log.error('error in request from WV license server: ' + str(e.errno) + ' | ' + e.message)
  63. return {'status': -1, 'errno': str(e.errno), 'message': e.message}
  64.  
  65. def buildCertificateRequest(request):
  66. """Builds JSON requests to be sent to the license server."""
  67. request = json.dumps({'payload': base64.standard_b64encode(request)})
  68. signature = generateSignature(request)
  69. if signature:
  70. certificate_request = json.dumps({"request": base64.standard_b64encode(request),
  71. "signature": signature,
  72. "signer": PROVIDER})
  73. return certificate_request
  74. else:
  75. log.error('sigrature error in buildCertificateRequest()')
  76.  
  77. def parseLicRequest(request):
  78. # payload = base64.standard_b64encode(request)
  79. req = json.dumps({
  80. "payload": base64.standard_b64encode(request),
  81. "provider": PROVIDER,
  82. "parse_only": True,
  83. "allowed_track_types":ALLOWED_TRACK_TYPES,
  84. "allow_unverified_platform":ALLOW_UNVERIFIED_PLATFORM
  85. })
  86. signature = generateSignature(req)
  87. parseServerRequest = json.dumps({
  88. "request": base64.standard_b64encode(req),
  89. "signature": signature,
  90. "signer": PROVIDER
  91. })
  92. # return json.loads(sendRequest(parseServerRequest))
  93. return json.loads(sendRequest(parseServerRequest))
  94.  
  95. def buildLicenseRequest(request, haveContentId = False, content_id = 0):
  96. # payload = base64.standard_b64encode(request)
  97. reqRaw = {
  98. "payload": base64.standard_b64encode(request),
  99. "provider": PROVIDER,
  100. "allowed_track_types":ALLOWED_TRACK_TYPES,
  101. "allow_unverified_platform":ALLOW_UNVERIFIED_PLATFORM
  102. }
  103. log.debug(reqRaw)
  104. if haveContentId:
  105. reqRaw["content_id"] = content_id
  106.  
  107. req = json.dumps(reqRaw)
  108.  
  109. signature = generateSignature(req)
  110. parseServerRequest = json.dumps({
  111. "request": base64.standard_b64encode(req),
  112. "signature": signature,
  113. "signer": PROVIDER
  114. })
  115.  
  116. return parseServerRequest
  117.  
  118. '''kinda' __main__'''
  119. def application(env, start_response):
  120.  
  121. log.debug("CONTENT_LENGTH: " + env.get('CONTENT_LENGTH', 0))
  122. try:
  123. if env.get('REQUEST_METHOD') == 'OPTIONS':
  124. log.info('sending OPTIONS')
  125. start_response('200 OK', [('Content-Type','text/html')])
  126. return ['OK']
  127. elif env.get('REQUEST_METHOD') == 'GET' or int(env.get('CONTENT_LENGTH', 0)) < 1: #TODO add other methods in exception
  128. log.error('got empty request')
  129. start_response('400', [('Content-Type','text/html')])
  130. return ['bad request']
  131. elif int(env.get('CONTENT_LENGTH', 0)) < 50:
  132. log.info('building certificate request')
  133. data = env['wsgi.input'].read()
  134. answer = json.loads(sendRequest(buildCertificateRequest(data)))
  135. if answer['status'] == 'OK' and answer.has_key('license'):
  136. #TODO Populate responses
  137. log.info('sending lic anwser')
  138. start_response('200 OK', [('Content-Type','text/html')])
  139. return [base64.standard_b64decode(answer["license"])]
  140. else:
  141. start_response('400 Error', [('Content-Type','text/html')])
  142. return ['go home']
  143. else:
  144. log.debug('building license request')
  145.  
  146. data = env['wsgi.input'].read()
  147. print(env['wsgi.input'].read())
  148. if True:#all(j in env.keys() for j in ['HTTP_X_QRV_CONTENT_ID', 'HTTP_X_QRV_SID']):
  149. # content_id = env.get('HTTP_X_QRV_CONTENT_ID', 0)
  150. # SID = env.get('HTTP_X_QRV_SID', 0)
  151. # log.debug("sid: " + SID + ' ' + "content_id: " + content_id)
  152. if PARSEFIRST:
  153. answer = parseLicRequest(data)
  154. if answer['status'] == 'OK':
  155. #TODO Populate responses
  156. log.debug("content_id: " + json.dumps(base64.standard_b64decode(answer["pssh_data"]["content_id"])))
  157. log.debug(answer["pssh_data"])
  158. log.debug('client info: ' + json.dumps(answer["client_info"], indent=4))
  159. answer = json.loads(sendRequest(buildLicenseRequest(data, haveContentId=True, content_id=answer["pssh_data"]["content_id"])))
  160. if answer['status'] == 'OK' and answer.has_key('license'):
  161. log.info(answer["license"])
  162. start_response('200 OK', [('Content-Type','text/html')])
  163. return [base64.standard_b64decode(answer["license"])]
  164. else:
  165. start_response('400 Error', [('Content-Type','text/html')])
  166. return ['go home']
  167. else:
  168. answer = json.loads(sendRequest(buildLicenseRequest(data, haveContentId=False)))
  169. if answer.has_key('status') and answer['status'] == 'OK' and answer.has_key('license'):
  170. start_response('200 OK', [('Content-Type','text/html')])
  171. return [base64.standard_b64decode(answer["license"])]
  172. else:
  173. if answer.has_key('status'):
  174. log.error('request denied. status: ' + answer['status'])
  175. start_response('500', [('Content-Type','text/html')])
  176. return ['request error']
  177. else:
  178. log.error('request error, no status code')
  179. start_response('500', [('Content-Type','text/html')])
  180. return ['request error']
  181. else:
  182. log.error('error parsing request header from client.')
  183. start_response('400', [('Content-Type','text/html')])
  184. return ['bad request']
  185. except Exception as e:
  186. log.error('error: ' + e.message)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement