Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- form -23nuyjabt3o6jyz20bze4lt19wjxqihqpzcja0kiy0osistaqb,-2jnri62v92sbs0qooyazpdfrwv2561kl49fulslch1thh43c0s,2qvew89xgsjkg0u0uhhmuxjxqp8kb71t6k827iaofkmepu7c47
- userName testuser
- uuid c8637a56-1495-4388-888b-0c35aff86974
- -23nuyjabt3o6jyz20bze4lt19wjxqihqpzcja0kiy0osistaqb
- -2jnri62v92sbs0qooyazpdfrwv2561kl49fulslch1thh43c0s a3a3574d05e0de1fa30d898e8ac425e44be2f19b7f8119a1ae27eeb4e3d0e445679554ba12fd44f120784465bc18cc512eaababec00a4ec9c03f11b2d64208ae
- 2qvew89xgsjkg0u0uhhmuxjxqp8kb71t6k827iaofkmepu7c47 testuser
- import configparser
- import logging
- import requests
- import sha3
- from logging.handlers import RotatingFileHandler
- from pathlib import Path
- from urllib.parse import urlparse, parse_qsl
- from bs4 import BeautifulSoup
- from getpass import getpass
- logger = logging.getLogger(__name__)
- handler = logging.StreamHandler()
- fh = RotatingFileHandler('log.txt', maxBytes=1024, backupCount=5)
- formatter = logging.Formatter(
- '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
- handler.setFormatter(formatter)
- fh.setFormatter(formatter)
- logger.addHandler(handler)
- logger.addHandler(fh)
- logger.setLevel(logging.DEBUG)
- config = configparser.ConfigParser()
- config.read('config.ini')
- URL = config['Penelope']['url']
- sess = requests.session()
- def get_uuid(username: str):
- """
- Returns a UUID for the provided username.
- :param username: Penelope User Name
- :return: str
- """
- try:
- r = sess.get(f'{URL}acm_loginControl')
- r = sess.post(f'{URL}acm_loginControl/uuid', {'userName': username})
- _uuid = r.json()['uuid']
- logger.debug(f'UUID Retrieved: {_uuid}')
- return _uuid
- except Exception as e:
- print(e)
- def digest_password(uuid: str, password: str):
- """
- Digests a password using **SHA3 (Keccak)** to match Crypto.JS lib used in Penelope login
- :param uuid: Generated UUID for username.
- :param password: pw to be digested
- :return: str
- """
- h = sha3.keccak_512()
- h.update(uuid.encode())
- h.update('algo != null && algo !== 0'.encode()) # Random string in Penelope JS script
- h.update(password.encode())
- hexdigest = h.hexdigest()
- logger.debug(f'Password Hashed: {hexdigest}')
- return hexdigest
- def login(username: str, digest: str):
- if 'authentype' not in sess.cookies or 'JSESSIONID' not in sess.cookies:
- try:
- # Gets token from login page
- r = sess.get(f'{URL}acm_loginControl')
- # Gets form IDs generated by server based off timestamp
- r = sess.get(f'{URL}acm_loginControl/login')
- # Set Credentials to form IDS
- form_ids = r.json()['form'].split(',')
- creds = {form_ids[0]: '', form_ids[2]: username, form_ids[1]: digest}
- # Post Credentials
- logger.debug('Trying to Log In')
- r = sess.post(f'{URL}acm_loginControl/login', creds)
- logger.debug(r.json())
- if r.json()['state'] == 'ok':
- logger.debug('Logged in Successfully')
- r = sess.get(f'{URL}acm_loginControl/create')
- r.raise_for_status()
- else:
- raise ValueError(r.json()['errorCode'])
- return r
- except ValueError as e:
- logger.error(e)
- except Exception as e:
- logger.error(e)
- else:
- logger.debug('Not Logging in')
- return f'Session already exists: {sess.cookies}'
- def navigate_to_workerprofile(user_id: int):
- return sess.get(f'{URL}acm_userProfileControl?actionType=view&kUserID={user_id}')
- def get_user_id(login_response: requests.models.Response):
- """Get Worker Profile kUserID (wruser table)"""
- soup = BeautifulSoup(login_response.content, 'html.parser')
- home_page_link = soup.find(id='frm_content_id')['src']
- r = sess.get(f'{URL}{home_page_link}')
- soup = BeautifulSoup(r.content, 'html.parser')
- href = next(link.get('href') for link in soup.find_all('a') if link.text == 'View My Profile')
- qs = urlparse(href)
- params = dict(parse_qsl(qs.query))
- logger.debug(f'kUserID Retrieved: {params["kUserID"]}')
- return params['kUserID']
- def find_log_attachments():
- logger.debug('Searching for stdout log files')
- soup = BeautifulSoup(r.content, 'html.parser')
- attachment_table = soup.find(id='attachListTable_worker')
- logs = [link.text for link in attachment_table.find_all('a') if link.text.startswith('stdout')]
- logger.debug(logs)
- return logs
- def download_attachment(file_name):
- download_url = f'{URL}acm_attachmentControl?actionType=download'
- f'&attachCat=worker&attachCatID={kuserid}&attachName={file_name}'
- logger.debug(f'Downloading {file_name}')
- r = sess.get(download_url)
- if 'JSESSIONID' not in sess.cookies:
- raise ConnectionError
- return r
- def save_log_files():
- log_attachments.sort()
- for log_name in log_attachments:
- log_file_path = Path(f'E:/Penelope Logs/RAQ.Athena-au.com/{log_name}')
- if not log_file_path.exists():
- try:
- log_download_response = download_attachment(log_name)
- with open(log_file_path, 'wb') as log_file:
- log_file.write(log_download_response.content)
- logger.debug(f'Log File {log_file_path} saved to disk')
- except ConnectionError as e:
- logger.error('Connection no longer valid. No session token.')
- else:
- logger.debug(f'{log_file_path} already exists')
- if __name__ == '__main__':
- if not config.has_option('Penelope', 'user'):
- user = input('Enter Username to login with')
- config['Penelope']['user'] = user
- if not config.has_option('Penelope', 'password'):
- password = getpass('Enter Password')
- user = config['Penelope']['user']
- uuid = get_uuid(user)
- digest = digest_password(uuid, password)
- config['Penelope']['password'] = digest
- with open('config.ini', 'w') as config_file:
- config.write(config_file)
- user = config['Penelope']['user']
- digest = config['Penelope']['password']
- r = login(user, digest)
- kuserid = get_user_id(r)
- r = navigate_to_workerprofile(kuserid)
- log_attachments = find_log_attachments()
- save_log_files()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement