1
2 import sys
3 import os
4 import subprocess
5 import xml.sax
6 import tempfile
7 import shutil
8 from base64 import encodestring
9 from up2date_client import up2dateLog
10 from up2date_client import rhnserver
11 from up2date_client import up2dateAuth
12 from up2date_client import up2dateErrors
13 from rhn.i18n import sstr, bstr
14
15 __rhnexport__ = [ 'xccdf_eval' ]
16
17 log = up2dateLog.initLog()
18
20 if cache_only:
21 return (0, 'no-ops for caching', {})
22
23 results_dir = None
24 if ('id' in args) and ('file_size' in args) and args['file_size'] > 0:
25 results_dir = tempfile.mkdtemp()
26 pwd = os.getcwd()
27 os.chdir(results_dir)
28
29 results_file = tempfile.NamedTemporaryFile(dir=results_dir)
30 params, oscap_err = _process_params(args['params'], results_file.name, results_dir)
31
32 oscap_err += _run_oscap(['xccdf', 'eval'] + params + [args['path']])
33 if results_dir:
34 os.chdir(pwd)
35
36 if not _assert_xml(results_file.file):
37 del(results_file)
38 _cleanup_temp(results_dir)
39 return (1, 'oscap tool did not produce valid xml.\n' + oscap_err, {})
40
41 ret, resume, xslt_err = _xccdf_resume(results_file.name, temp_dir=results_dir)
42 if ret != 0 or resume == '':
43 del(results_file)
44 _cleanup_temp(results_dir)
45 return (1, 'Problems with extracting resume:\n' + xslt_err, {})
46
47 try:
48 up_err = _upload_results(results_file, results_dir, args)
49 except:
50
51 log.log_exception(*sys.exc_info())
52 up_err = "Upload of detailed results failed. Fatal error in Python code occurred"
53 del(results_file)
54 _cleanup_temp(results_dir)
55 return (0, 'openscap scan completed', {
56 'resume': encodestring(resume),
57 'errors': encodestring(bstr(oscap_err) + bstr(xslt_err) + bstr(up_err))
58 })
59
61 dev_null = open('/dev/null', mode="ab+")
62 c = _popen(['/usr/bin/oscap'] + arguments, stdout=dev_null.fileno())
63 ret = c.wait()
64 dev_null.close()
65 errors = sstr(c.stderr.read())
66 if ret != 0:
67 errors += 'xccdf_eval: oscap tool returned %i\n' % ret
68 log.log_debug('The oscap tool completed\n%s' % errors)
69 return errors
70
72 xslt = '/usr/share/openscap/xsl/xccdf-resume.xslt'
73
74 dev_null = open('/dev/null', mode="ab+")
75 resume_file = tempfile.NamedTemporaryFile(dir=temp_dir)
76 c = _popen(['/usr/bin/xsltproc', '--output', resume_file.name,
77 xslt, results_file], stdout=dev_null.fileno())
78 ret = c.wait()
79 dev_null.close()
80
81 errors = sstr(c.stderr.read())
82 if ret != 0:
83 errors += 'xccdf_eval: xsltproc tool returned %i\n' % ret
84 log.log_debug('The xsltproc tool completed:\n%s' % errors)
85
86 resume = resume_file.read()
87 del(resume_file)
88 return ret, resume, errors
89
90 -def _popen(args, stdout=subprocess.PIPE):
91 log.log_debug('Running: ' + str(args))
92 return subprocess.Popen(args, bufsize=-1, stdin=subprocess.PIPE,
93 stdout=stdout, stderr=subprocess.PIPE, shell=False)
94
96 params = ['--results', filename]
97 if results_dir:
98 params += ['--oval-results', '--report', 'xccdf-report.html']
99 errors = ''
100 if args:
101 allowed_args = {
102 '--profile': 1,
103 '--skip-valid': 0,
104 '--cpe': 1,
105 '--fetch-remote-resources': 0,
106 '--datastream-id': 1,
107 '--xccdf-id': 1,
108 '--tailoring-id': 1,
109 '--tailoring-file': 1,
110 }
111 args = args.split(' ')
112 i = 0
113 while i < len(args):
114 if args[i] in allowed_args:
115 j = i + allowed_args[args[i]]
116 params += args[i:j+1]
117 i = j
118 elif not errors:
119 errors = 'xccdf_eval: Following arguments forbidden: ' + args[i]
120 else:
121 errors += ' ' + args[i]
122 i += 1
123 if errors:
124 errors += '\n'
125 return params, errors
126
145
146 -def _upload_file(server, systemid, args, path, filename, f):
147 if filename != 'xccdf-report.html' and not _assert_xml(f):
148 log.log_debug('Excluding "%s" file from upload. Not an XML.' % path)
149 return '\nxccdf_eval: File "%s" not uploaded. Not an XML file format.' % filename
150
151 stat = os.fstat(f.fileno())
152 if stat.st_size < args['file_size']:
153 try:
154 ret = server.scap.upload_result(systemid, args['id'],
155 {'filename': filename,
156 'filecontent': encodestring(f.read()),
157 'content-encoding': 'base64',
158 })
159 if ret and ret['result']:
160 log.log_debug('The file %s uploaded successfully.' % filename)
161 return ''
162 except up2dateErrors.Error:
163 e = sys.exc_info()[1]
164 log.log_exception(*sys.exc_info())
165 return '\nxccdf_eval: File "%s" not uploaded. %s' % (filename, e)
166 else:
167 return '\nxccdf_eval: File "%s" not uploaded. File size (%d B) exceeds the limit.' \
168 % (filename, stat.st_size)
169
171 if results_dir:
172 shutil.rmtree(results_dir)
173
175 try:
176 try:
177 content = f.read()
178 xml.sax.parseString(content, xml.sax.ContentHandler())
179 return True
180 except Exception:
181 log.log_exception(*sys.exc_info())
182 return False
183 finally:
184 f.seek(0)
185