Advertisement
Guest User

Untitled

a guest
Feb 28th, 2019
151
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.21 KB | None | 0 0
  1. form -23nuyjabt3o6jyz20bze4lt19wjxqihqpzcja0kiy0osistaqb,-2jnri62v92sbs0qooyazpdfrwv2561kl49fulslch1thh43c0s,2qvew89xgsjkg0u0uhhmuxjxqp8kb71t6k827iaofkmepu7c47
  2.  
  3. userName testuser
  4.  
  5. uuid c8637a56-1495-4388-888b-0c35aff86974
  6.  
  7. -23nuyjabt3o6jyz20bze4lt19wjxqihqpzcja0kiy0osistaqb
  8. -2jnri62v92sbs0qooyazpdfrwv2561kl49fulslch1thh43c0s a3a3574d05e0de1fa30d898e8ac425e44be2f19b7f8119a1ae27eeb4e3d0e445679554ba12fd44f120784465bc18cc512eaababec00a4ec9c03f11b2d64208ae
  9. 2qvew89xgsjkg0u0uhhmuxjxqp8kb71t6k827iaofkmepu7c47 testuser
  10.  
  11. import configparser
  12. import logging
  13. import requests
  14. import sha3
  15. from logging.handlers import RotatingFileHandler
  16. from pathlib import Path
  17. from urllib.parse import urlparse, parse_qsl
  18. from bs4 import BeautifulSoup
  19. from getpass import getpass
  20.  
  21. logger = logging.getLogger(__name__)
  22. handler = logging.StreamHandler()
  23. fh = RotatingFileHandler('log.txt', maxBytes=1024, backupCount=5)
  24. formatter = logging.Formatter(
  25. '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
  26. handler.setFormatter(formatter)
  27. fh.setFormatter(formatter)
  28. logger.addHandler(handler)
  29. logger.addHandler(fh)
  30. logger.setLevel(logging.DEBUG)
  31.  
  32.  
  33. config = configparser.ConfigParser()
  34. config.read('config.ini')
  35. URL = config['Penelope']['url']
  36.  
  37. sess = requests.session()
  38.  
  39.  
  40. def get_uuid(username: str):
  41. """
  42. Returns a UUID for the provided username.
  43. :param username: Penelope User Name
  44. :return: str
  45. """
  46. try:
  47. r = sess.get(f'{URL}acm_loginControl')
  48. r = sess.post(f'{URL}acm_loginControl/uuid', {'userName': username})
  49. _uuid = r.json()['uuid']
  50. logger.debug(f'UUID Retrieved: {_uuid}')
  51. return _uuid
  52. except Exception as e:
  53. print(e)
  54.  
  55.  
  56. def digest_password(uuid: str, password: str):
  57. """
  58. Digests a password using **SHA3 (Keccak)** to match Crypto.JS lib used in Penelope login
  59. :param uuid: Generated UUID for username.
  60. :param password: pw to be digested
  61. :return: str
  62. """
  63. h = sha3.keccak_512()
  64.  
  65. h.update(uuid.encode())
  66. h.update('algo != null && algo !== 0'.encode()) # Random string in Penelope JS script
  67. h.update(password.encode())
  68.  
  69. hexdigest = h.hexdigest()
  70. logger.debug(f'Password Hashed: {hexdigest}')
  71. return hexdigest
  72.  
  73.  
  74. def login(username: str, digest: str):
  75. if 'authentype' not in sess.cookies or 'JSESSIONID' not in sess.cookies:
  76. try:
  77. # Gets token from login page
  78. r = sess.get(f'{URL}acm_loginControl')
  79. # Gets form IDs generated by server based off timestamp
  80. r = sess.get(f'{URL}acm_loginControl/login')
  81.  
  82. # Set Credentials to form IDS
  83. form_ids = r.json()['form'].split(',')
  84. creds = {form_ids[0]: '', form_ids[2]: username, form_ids[1]: digest}
  85.  
  86. # Post Credentials
  87. logger.debug('Trying to Log In')
  88. r = sess.post(f'{URL}acm_loginControl/login', creds)
  89. logger.debug(r.json())
  90. if r.json()['state'] == 'ok':
  91. logger.debug('Logged in Successfully')
  92. r = sess.get(f'{URL}acm_loginControl/create')
  93. r.raise_for_status()
  94. else:
  95. raise ValueError(r.json()['errorCode'])
  96. return r
  97. except ValueError as e:
  98. logger.error(e)
  99.  
  100. except Exception as e:
  101. logger.error(e)
  102.  
  103. else:
  104. logger.debug('Not Logging in')
  105. return f'Session already exists: {sess.cookies}'
  106.  
  107.  
  108. def navigate_to_workerprofile(user_id: int):
  109. return sess.get(f'{URL}acm_userProfileControl?actionType=view&kUserID={user_id}')
  110.  
  111.  
  112. def get_user_id(login_response: requests.models.Response):
  113. """Get Worker Profile kUserID (wruser table)"""
  114. soup = BeautifulSoup(login_response.content, 'html.parser')
  115. home_page_link = soup.find(id='frm_content_id')['src']
  116. r = sess.get(f'{URL}{home_page_link}')
  117. soup = BeautifulSoup(r.content, 'html.parser')
  118. href = next(link.get('href') for link in soup.find_all('a') if link.text == 'View My Profile')
  119. qs = urlparse(href)
  120. params = dict(parse_qsl(qs.query))
  121. logger.debug(f'kUserID Retrieved: {params["kUserID"]}')
  122. return params['kUserID']
  123.  
  124. def find_log_attachments():
  125. logger.debug('Searching for stdout log files')
  126. soup = BeautifulSoup(r.content, 'html.parser')
  127. attachment_table = soup.find(id='attachListTable_worker')
  128. logs = [link.text for link in attachment_table.find_all('a') if link.text.startswith('stdout')]
  129. logger.debug(logs)
  130. return logs
  131.  
  132.  
  133. def download_attachment(file_name):
  134. download_url = f'{URL}acm_attachmentControl?actionType=download'
  135. f'&attachCat=worker&attachCatID={kuserid}&attachName={file_name}'
  136. logger.debug(f'Downloading {file_name}')
  137. r = sess.get(download_url)
  138. if 'JSESSIONID' not in sess.cookies:
  139. raise ConnectionError
  140. return r
  141.  
  142.  
  143. def save_log_files():
  144. log_attachments.sort()
  145. for log_name in log_attachments:
  146. log_file_path = Path(f'E:/Penelope Logs/RAQ.Athena-au.com/{log_name}')
  147.  
  148. if not log_file_path.exists():
  149. try:
  150. log_download_response = download_attachment(log_name)
  151. with open(log_file_path, 'wb') as log_file:
  152. log_file.write(log_download_response.content)
  153. logger.debug(f'Log File {log_file_path} saved to disk')
  154. except ConnectionError as e:
  155. logger.error('Connection no longer valid. No session token.')
  156. else:
  157. logger.debug(f'{log_file_path} already exists')
  158.  
  159. if __name__ == '__main__':
  160. if not config.has_option('Penelope', 'user'):
  161. user = input('Enter Username to login with')
  162. config['Penelope']['user'] = user
  163. if not config.has_option('Penelope', 'password'):
  164. password = getpass('Enter Password')
  165. user = config['Penelope']['user']
  166. uuid = get_uuid(user)
  167. digest = digest_password(uuid, password)
  168. config['Penelope']['password'] = digest
  169. with open('config.ini', 'w') as config_file:
  170. config.write(config_file)
  171.  
  172. user = config['Penelope']['user']
  173. digest = config['Penelope']['password']
  174.  
  175. r = login(user, digest)
  176. kuserid = get_user_id(r)
  177. r = navigate_to_workerprofile(kuserid)
  178. log_attachments = find_log_attachments()
  179. save_log_files()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement