-
Notifications
You must be signed in to change notification settings - Fork 345
/
Tnscmd.py
144 lines (135 loc) · 5.01 KB
/
Tnscmd.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/usr/bin/python
# -*- coding: utf-8 -*-
import logging,struct, socket, re, struct
from Constants import *
from Utils import checkOptionsGivenByTheUser
class Tnscmd():
'''
Get information about the oracle database service
'''
def __init__(self,args):
'''
Constructor
'''
logging.debug("Tnscmd object created")
self.args = args
self.recvdata = ""
self.alias = []
self.version = ""
self.localIP = ""
def getRecvData(self):
'''
return a representation of received data
'''
return repr(self.recvdata)
def getInformation(self,cmd='ping'):
'''
Get information about the oracle database service
Returns False if an error
Returns True if it has a response
'''
logging.info ("alias list emptied")
self.recvdata = ""
command = "(CONNECT_DATA=(COMMAND={0}))".format(cmd)
commandlen = len(command)
#logging.info("Sending {0} to {1}:{2} in order to get ALIAS".format(command,self.args['server'],self.args['port']))
clenH = commandlen >> 8
clenL = commandlen & 0xff
# calculate packet length
packetlen = commandlen + 58; # "preamble" is 58 bytes
plenH = packetlen >> 8
plenL = packetlen & 0xff
# decimal offset
# 0: packetlen_high packetlen_low
# 26: cmdlen_high cmdlen_low
# 58: command
packet = [plenH, plenL, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
0x01, 0x36, 0x01, 0x2c, 0x00, 0x00, 0x08, 0x00,
0x7f, 0xff, 0x7f, 0x08, 0x00, 0x00, 0x00, 0x01,
clenH, clenL, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x34, 0xe6, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00]
#put the command in packet
for c in command : packet.append(ord(c))
sendbuf = b''.join([struct.pack('B', val) for val in packet])
#logging.debug("connect to this service")
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(TIMEOUT_TNS_CMD)
logging.debug("Connection to {0}:{1}".format(self.args['server'],int(self.args['port'])))
s.connect((self.args['server'],int(self.args['port'])))
self.localIP = s.getsockname()[0]
logging.debug("writing {0} bytes: {1}".format(len(sendbuf),repr(sendbuf)))
s.sendall(sendbuf)
logging.debug("reading data")
# read until socket EOF
self.recvdata = str(s.recv(999999))
s.close()
except socket.timeout as e:
logging.critical("Connection Timeout: The server has not responded to the CONNECT_DATA packet send")
return False
except Exception as e:
logging.critical("Connection Error: {0}".format(e))
return False
# 1st 12 bytes have some meaning which so far eludes me
logging.info("Data received thanks to the '{1}' cmd: {0}".format(repr(self.recvdata),cmd))
return True
def getAlias(self):
'''
return alias list or None if an error
'''
self.alias = []
status = self.getInformation(cmd='ping')
if status == False:
return None
alias = re.findall(r'(?<=ALIAS=).+?(?=\))', self.recvdata, flags=re.IGNORECASE)
for anAlias in alias : self.alias.append(anAlias.replace('\n','').replace(' ','').replace('\t',''))
return self.alias
def getVersion(self):
'''
return version from VSNNUM or None if an error
'''
self.version = ""
status = self.getInformation(cmd='version')
if status == False:
return None
vsnnum = re.findall(r'(?<=VSNNUM=).+?(?=\))', self.recvdata, flags=re.IGNORECASE)
if vsnnum == []:
return "Unknown"
else:
hexVsnnum = str(hex(int(vsnnum[0])))[2:]
if len(hexVsnnum) == 7:
hexVersionList = struct.unpack('cc2sc2s',hexVsnnum.encode())
elif len(hexVsnnum) == 8:
hexVersionList = struct.unpack('2sc2sc2s',hexVsnnum.encode())
for v in hexVersionList : self.version += str(int(v,16)) + '.'
return self.version
def runTnsCmdModule(args):
'''
run the TNS cmd module
'''
if checkOptionsGivenByTheUser(args,["version","status","ping"],checkSID=False,checkAccount=False) == False : return EXIT_MISS_ARGUMENT
tnscmd = Tnscmd(args)
if args['ping'] == True:
args['print'].title("Searching ALIAS on the {0} server, port {1}".format(args['server'],args['port']))
alias = tnscmd.getAlias()
if alias != None:
args['print'].goodNews("{0} ALIAS received: {1}. You should use this alias (more or less) as Oracle SID.".format(len(alias),alias))
else:
args['print'].badNews("Impossible to get ALIAS")
if args['version'] == True:
args['print'].title("Searching the version of the Oracle database server ({0}) listening on the port {1}".format(args['server'],args['port']))
version = tnscmd.getVersion()
if version != None:
args['print'].goodNews("The remote database version is: '{0}'".format(version))
else:
args['print'].badNews("Impossible to get version")
if args['status'] == True:
args['print'].title("Searching the server status of the Oracle database server ({0}) listening on the port {1}".format(args['server'],args['port']))
status = tnscmd.getInformation(cmd='status')
if status != False:
args['print'].goodNews("Data received by the database server: '{0}'".format(tnscmd.getRecvData()))
else:
args['print'].badNews("Impossible to get status")