Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix initialization under reduced privileges #55

Merged
merged 1 commit into from
Jan 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
Revision 0.4.6, released XX-01-2019
-----------------------------------

- The `--log-level` option added
- Default daemon syslog service destination to a local socket
- Fixed timed log file rotation to respect log file creation time
when computing next rotation time
- Fixed possible file permission issues by initializing pysnmp modules,
logger and variation modules subsystems under reduced user privileges
- Improve error reporting in `notification` variation module

Revision 0.4.5, released 30-12-2018
Expand Down
90 changes: 52 additions & 38 deletions scripts/pcap2dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
from snmpsim import confdir, error, log

# Defaults
PROGRAM_NAME = 'pcap2dev'
verboseFlag = True
mibSources = []
defaultMibSources = ['http://mibs.snmplabs.com/asn1/@mib@']
Expand All @@ -40,6 +41,8 @@
promiscuousMode = False
outputDir = '.'
transportIdOffset = 0
loggingMethod = ['stderr']
loggingLevel = None
variationModuleOptions = ""
variationModuleName = variationModule = None
listenInterface = captureFile = None
Expand Down Expand Up @@ -69,6 +72,7 @@
[--debug-asn1=<%s>]
[--quiet]
[--logging-method=<%s[:args]>]
[--log-level=<%s>]
[--mib-source=<url>]
[--start-object=<MIB-NAME::[symbol-name]|OID>]
[--stop-object=<MIB-NAME::[symbol-name]|OID>]
Expand All @@ -85,20 +89,22 @@
'|'.join([x for x in getattr(pysnmp_debug, 'FLAG_MAP', getattr(pysnmp_debug, 'flagMap', ()))
if x != 'mibview']),
'|'.join([x for x in getattr(pyasn1_debug, 'FLAG_MAP', getattr(pyasn1_debug, 'flagMap', ()))]),
'|'.join(log.gMap)
'|'.join(log.METHODS_MAP),
'|'.join(log.LEVELS_MAP)
)

try:
opts, params = getopt.getopt(sys.argv[1:], 'hv', [
'help', 'version', 'debug=', 'debug-snmp=', 'debug-asn1=',
'quiet', 'logging-method=', 'start-oid=', 'stop-oid=',
'quiet', 'logging-method=', 'log-level=', 'start-oid=', 'stop-oid=',
'start-object=', 'stop-object=', 'mib-source=',
'output-dir=', 'transport-id-offset=',
'capture-file=', 'listen-interface=', 'promiscuous-mode',
'packet-filter=',
'variation-modules-dir=', 'variation-module=',
'variation-module-options='
])

except Exception:
sys.stderr.write(
'ERROR: %s\r\n%s\r\n' % (sys.exc_info()[1], helpMessage))
Expand Down Expand Up @@ -145,12 +151,9 @@
pyasn1_debug.setLogger(pyasn1_debug.Debug(*opt[1].split(','), **dict(
loggerName='pcap2dev.pyasn1')))
elif opt[0] == '--logging-method':
try:
log.setLogger('pcap2dev', *opt[1].split(':'), **dict(force=True))
except error.SnmpsimError:
sys.stderr.write(
'%s\r\n%s\r\n' % (sys.exc_info()[1], helpMessage))
sys.exit(-1)
loggingMethod = opt[1].split(':')
elif opt[0] == '--log-level':
loggingLevel = opt[1]
if opt[0] == '--quiet':
verboseFlag = False
# obsolete begin
Expand Down Expand Up @@ -199,7 +202,15 @@
sys.stderr.write('ERROR: pylibpcap package is missing!\r\nGet it by running `pip install https://downloads.sourceforge.net/project/pylibpcap/pylibpcap/0.6.4/pylibpcap-0.6.4.tar.gz`\r\n%s\r\n' % helpMessage)
sys.exit(-1)

log.setLogger('pcap2dev', 'stdout')
try:
log.setLogger(PROGRAM_NAME, *loggingMethod, force=True)

if loggingLevel:
log.setLevel(loggingLevel)

except error.SnmpsimError:
sys.stderr.write('%s\r\n%s\r\n' % (sys.exc_info()[1], helpMessage))
sys.exit(1)

if isinstance(startOID, rfc1902.ObjectIdentity) or \
isinstance(stopOID, rfc1902.ObjectIdentity):
Expand All @@ -219,14 +230,14 @@

if variationModuleName:
for variationModulesDir in confdir.variation:
log.msg('Scanning "%s" directory for variation modules...' % variationModulesDir)
log.info('Scanning "%s" directory for variation modules...' % variationModulesDir)
if not os.path.exists(variationModulesDir):
log.msg('Directory "%s" does not exist' % variationModulesDir)
log.info('Directory "%s" does not exist' % variationModulesDir)
continue

mod = os.path.join(variationModulesDir, variationModuleName + '.py')
if not os.path.exists(mod):
log.msg('Variation module "%s" not found' % mod)
log.info('Variation module "%s" not found' % mod)
continue

ctx = {'path': mod, 'moduleContext': {}}
Expand All @@ -238,34 +249,36 @@
execfile(mod, ctx)

except Exception:
log.msg('Variation module "%s" execution failure: %s' % (mod, sys.exc_info()[1]))
log.error('Variation module "%s" execution failure: %s' % (mod, sys.exc_info()[1]))
sys.exit(-1)

else:
variationModule = ctx
log.msg('Variation module "%s" loaded' % variationModuleName)
log.info('Variation module "%s" loaded' % variationModuleName)
break
else:
log.msg('ERROR: variation module "%s" not found' % variationModuleName)
log.error('variation module "%s" not found' % variationModuleName)
sys.exit(-1)

# Variation module initialization

if variationModule:
log.msg('Initializing variation module...')
log.info('Initializing variation module...')
for x in ('init', 'record', 'shutdown'):
if x not in variationModule:
log.msg('ERROR: missing "%s" handler at variation module "%s"' % (x, variationModuleName))
log.error('missing "%s" handler at variation module "%s"' % (x, variationModuleName))
sys.exit(-1)
try:
variationModule['init'](options=variationModuleOptions,
mode='recording',
startOID=startOID,
stopOID=stopOID)

except Exception:
log.msg('Variation module "%s" initialization FAILED: %s' % (variationModuleName, sys.exc_info()[1]))
log.error('Variation module "%s" initialization FAILED: %s' % (variationModuleName, sys.exc_info()[1]))

else:
log.msg('Variation module "%s" initialization OK' % variationModuleName)
log.info('Variation module "%s" initialization OK' % variationModuleName)


# Data file builder
Expand Down Expand Up @@ -301,31 +314,31 @@ def formatValue(self, oid, value, **context):

if listenInterface:
if verboseFlag:
log.msg('Listening on interface %s in %spromiscuous mode' % (listenInterface, promiscuousMode is False and 'non-' or ''))
log.info('Listening on interface %s in %spromiscuous mode' % (listenInterface, promiscuousMode is False and 'non-' or ''))
try:
pcapObj.open_live(listenInterface, 65536, promiscuousMode, 1000)
except Exception:
log.msg('Error opening interface %s for snooping: %s' % (listenInterface, sys.exc_info()[1]))
log.error('Error opening interface %s for snooping: %s' % (listenInterface, sys.exc_info()[1]))
sys.exit(-1)
elif captureFile:
if verboseFlag:
log.msg('Opening capture file %s' % captureFile)
log.info('Opening capture file %s' % captureFile)
try:
pcapObj.open_offline(captureFile)
except Exception:
log.msg('Error opening capture file %s for reading: %s' % (captureFile, sys.exc_info()[1]))
log.error('Error opening capture file %s for reading: %s' % (captureFile, sys.exc_info()[1]))
sys.exit(-1)
else:
sys.stderr.write('ERROR: no capture file or live interface specified\r\n%s\r\n' % helpMessage)
sys.exit(-1)

if packetFilter:
if verboseFlag:
log.msg('Applying packet filter \"%s\"' % packetFilter)
log.info('Applying packet filter \"%s\"' % packetFilter)
pcapObj.setfilter(packetFilter, 0, 0)

if verboseFlag:
log.msg('Processing records from %s till %s' % (startOID or 'the beginning', stopOID or 'the end'))
log.info('Processing records from %s till %s' % (startOID or 'the beginning', stopOID or 'the end'))


def parsePacket(s):
Expand Down Expand Up @@ -435,19 +448,19 @@ def handlePacket(pktlen, data, timestamp):

try:
if listenInterface:
log.msg(
log.info(
'Listening on interface "%s", kill me when you are done.' % listenInterface)
while True:
pcapObj.dispatch(1, handlePacket)
elif captureFile:
log.msg('Processing capture file "%s"....' % captureFile)
log.info('Processing capture file "%s"....' % captureFile)
args = pcapObj.next()
while args:
handlePacket(*args)
args = pcapObj.next()

except (TypeError, KeyboardInterrupt):
log.msg('Shutting down process...')
log.info('Shutting down process...')

except Exception:
exc_info = sys.exc_info()
Expand All @@ -458,15 +471,15 @@ def handlePacket(pktlen, data, timestamp):
filename = os.path.join(outputDir,
context + os.path.extsep + SnmprecRecord.ext)
if verboseFlag:
log.msg('Creating simulation context %s at %s' % (context, filename))
log.info('Creating simulation context %s at %s' % (context, filename))
try:
os.mkdir(os.path.dirname(filename))
except OSError:
pass
try:
outputFile = open(filename, 'wb')
except IOError:
log.msg('ERROR: writing %s: %s' % (filename, sys.exc_info()[1]))
log.error('writing %s: %s' % (filename, sys.exc_info()[1]))
sys.exit(-1)

count = total = iteration = 0
Expand Down Expand Up @@ -523,14 +536,14 @@ def handlePacket(pktlen, data, timestamp):
moreDataNotification = sys.exc_info()[1]
if 'period' in moreDataNotification:
timeOffset += moreDataNotification['period']
log.msg(
log.info(
'%s OIDs dumped, advancing time window to %.2f sec(s)...' % (total, timeOffset))
break

except error.NoDataNotification:
pass
except error.SnmpsimError:
log.msg('ERROR: %s' % (sys.exc_info()[1],))
log.error((sys.exc_info()[1],))
continue
else:
outputFile.write(line)
Expand All @@ -545,22 +558,23 @@ def handlePacket(pktlen, data, timestamp):
outputFile.close()

if variationModule:
log.msg('Shutting down variation module "%s"...' % variationModuleName)
log.info('Shutting down variation module "%s"...' % variationModuleName)
try:
variationModule['shutdown'](options=variationModuleOptions,
mode='recording')
except Exception:
log.msg('Variation module "%s" shutdown FAILED: %s' % (variationModuleName, sys.exc_info()[1]))
log.error('Variation module "%s" shutdown FAILED: %s' % (variationModuleName, sys.exc_info()[1]))

else:
log.msg('Variation module "%s" shutdown OK' % variationModuleName)
log.info('Variation module "%s" shutdown OK' % variationModuleName)

log.msg("""PCap statistics:
log.info("""PCap statistics:
packets snooped: %s
packets dropped: %s
packets dropped: by interface %s""" % pcapObj.stats())
log.msg("""SNMP statistics:
log.info("""SNMP statistics:
%s""" % ' '.join(['%s: %s\r\n' % kv for kv in stats.items()]))

if exc_info:
for line in traceback.format_exception(*exc_info):
log.msg(line.replace('\n', ';'))
log.error(line.replace('\n', ';'))
Loading