some changes to the web UI to defend against XSS

This commit is contained in:
Mike Bonnet 2009-02-11 16:38:25 -05:00
parent 182a179a52
commit d4836ac43c
4 changed files with 59 additions and 27 deletions

View file

@ -414,6 +414,18 @@ def hello(req):
def showSession(req):
return _getServer(req).showSession()
# All Tasks
_TASKS = ['build',
'buildSRPMFromSCM',
'buildArch',
'chainbuild',
'waitrepo',
'tagBuild',
'newRepo',
'createrepo',
'buildNotification',
'tagNotification',
'dependantTask']
# Tasks that can exist without a parent
_TOPLEVEL_TASKS = ['build', 'buildNotification', 'chainbuild', 'newRepo', 'tagBuild', 'tagNotification', 'waitrepo']
# Tasks that can have children
@ -437,6 +449,13 @@ def tasks(req, owner=None, state='active', view='tree', method='all', hostID=Non
values['users'] = server.listUsers(queryOpts={'order': 'name'})
if method in _TASKS:
opts['method'] = method
else:
method = 'all'
values['method'] = method
values['alltasks'] = _TASKS
treeEnabled = True
if hostID or (method not in ['all'] + _PARENT_TASKS):
# force flat view if we're filtering by a hostID or a task that never has children
@ -462,10 +481,6 @@ def tasks(req, owner=None, state='active', view='tree', method='all', hostID=Non
treeDisplay = False
values['treeDisplay'] = treeDisplay
if method != 'all':
opts['method'] = method
values['method'] = method
if view in ('tree', 'toplevel'):
opts['parent'] = None
@ -721,6 +736,8 @@ def tags(req, start=None, order=None, childID=None):
return _genHTML(req, 'tags.chtml')
_PREFIX_CHARS = [chr(char) for char in range(48, 58) + range(97, 123)]
def packages(req, tagID=None, userID=None, order='package_name', start=None, prefix=None, inherited='1'):
values = _initValues(req, 'Packages', 'packages')
server = _getServer(req)
@ -738,7 +755,9 @@ def packages(req, tagID=None, userID=None, order='package_name', start=None, pre
values['user'] = user
values['order'] = order
if prefix:
prefix = prefix.lower()
prefix = prefix.lower()[0]
if prefix not in _PREFIX_CHARS:
prefix = None
values['prefix'] = prefix
inherited = int(inherited)
values['inherited'] = inherited
@ -747,7 +766,7 @@ def packages(req, tagID=None, userID=None, order='package_name', start=None, pre
kw={'tagID': tagID, 'userID': userID, 'prefix': prefix, 'inherited': bool(inherited)},
start=start, dataName='packages', prefix='package', order=order)
values['chars'] = [chr(char) for char in range(48, 58) + range(97, 123)]
values['chars'] = _PREFIX_CHARS
return _genHTML(req, 'packages.chtml')
@ -1110,7 +1129,9 @@ def builds(req, userID=None, tagID=None, packageID=None, state=None, order='-com
values['state'] = state
if prefix:
prefix = prefix.lower()
prefix = prefix.lower()[0]
if prefix not in _PREFIX_CHARS:
prefix = None
values['prefix'] = prefix
values['order'] = order
@ -1135,7 +1156,7 @@ def builds(req, userID=None, tagID=None, packageID=None, state=None, order='-com
'state': state, 'prefix': prefix},
start=start, dataName='builds', prefix='build', order=order)
values['chars'] = [chr(char) for char in range(48, 58) + range(97, 123)]
values['chars'] = _PREFIX_CHARS
return _genHTML(req, 'builds.chtml')
@ -1144,7 +1165,9 @@ def users(req, order='name', start=None, prefix=None):
server = _getServer(req)
if prefix:
prefix = prefix.lower()
prefix = prefix.lower()[0]
if prefix not in _PREFIX_CHARS:
prefix = None
values['prefix'] = prefix
values['order'] = order
@ -1152,7 +1175,7 @@ def users(req, order='name', start=None, prefix=None):
users = kojiweb.util.paginateMethod(server, values, 'listUsers', kw={'prefix': prefix},
start=start, dataName='users', prefix='user', order=order)
values['chars'] = [chr(char) for char in range(48, 58) + range(97, 123)]
values['chars'] = _PREFIX_CHARS
return _genHTML(req, 'users.chtml')
@ -1848,10 +1871,15 @@ _infoURLs = {'package': 'packageinfo?packageID=%(id)i',
'host': 'hostinfo?hostID=%(id)i',
'rpm': 'rpminfo?rpmID=%(id)i',
'file': 'fileinfo?rpmID=%(id)i&filename=%(name)s'}
_VALID_SEARCH_CHARS = r"""a-zA-Z0-9"""
_VALID_SEARCH_SYMS = r"""@.,_/\()%+-*?|[]^$"""
_VALID_SEARCH_RE = re.compile('^[' + _VALID_SEARCH_CHARS + re.escape(_VALID_SEARCH_SYMS) + ']+$')
def search(req, start=None, order='name'):
values = _initValues(req, 'Search', 'search')
server = _getServer(req)
values['error'] = None
form = req.form
if form.has_key('terms') and form['terms']:
@ -1862,12 +1890,19 @@ def search(req, start=None, order='name'):
values['type'] = type
values['match'] = match
if not _VALID_SEARCH_RE.match(terms):
values['error'] = 'Invalid search terms<br/>' + \
'Search terms may contain only these characters: ' + \
_VALID_SEARCH_CHARS + _VALID_SEARCH_SYMS
return _genHTML(req, 'search.chtml')
if match == 'regexp':
try:
re.compile(terms)
except:
raise koji.GenericError, 'invalid regular expression: %s' % terms
values['error'] = 'Invalid regular expression'
return _genHTML(req, 'search.chtml')
infoURL = _infoURLs.get(type)
if not infoURL:
raise koji.GenericError, 'unknown search type: %s' % type

View file

@ -7,6 +7,9 @@
<form action="search">
<table>
<tr>
#if $error
<tr><td colspan="3" class="error">$error</td></tr>
#end if
<th>Search</th>
<td><input type="text" name="terms"/></td>
<td>
@ -26,7 +29,7 @@
<td colspan="2">
<input type="radio" name="match" value="glob" id="radioglob" checked="checked"/><abbr title="? will match any single character, * will match any sequence of zero or more characters" id="abbrglob">glob</abbr>
<input type="radio" name="match" value="regexp" id="radioregexp"/><abbr title="full POSIX regular expressions" id="abbrregexp">regexp</abbr>
<input type="radio" name="match" value="exact" id="radioexact"/><abbr title="exact matches only" id="abbrexact">exact</abbr>
<input type="radio" name="match" value="exact" id="radioexact"/><abbr title="exact matches only" id="abbrexact">exact</abbr>
</td>
</tr>
<tr>

View file

@ -78,19 +78,9 @@ All
</td><td>
<select name="method" class="filterlist" onchange="javascript: window.location = 'tasks?method=' + this.value + '$util.passthrough_except($self, 'method')';">
<option value="all" $util.toggleSelected($self, $method, 'all')>all</option>
<option value="build" #if $method == 'build' then 'selected="selected"' else ''#>build</option>
<option value="buildSRPMFromSCM" #if $method == 'buildSRPMFromSCM' then 'selected="selected"' else ''#>buildSRPMFromSCM</option>
<option value="buildSRPMFromCVS" #if $method == 'buildSRPMFromCVS' then 'selected="selected"' else ''#>buildSRPMFromCVS</option>
<option value="buildArch" #if $method == 'buildArch' then 'selected="selected"' else ''#>buildArch</option>
<option value="buildNotification" #if $method == 'buildNotification' then 'selected="selected"' else ''#>buildNotification</option>
<option value="tagBuild" #if $method == 'tagBuild' then 'selected="selected"' else ''#>tagBuild</option>
<option value="tagNotification" #if $method == 'tagNotification' then 'selected="selected"' else ''#>tagNotification</option>
<option value="newRepo" #if $method == 'newRepo' then 'selected="selected"' else ''#>newRepo</option>
<option value="prepRepo" #if $method == 'prepRepo' then 'selected="selected"' else ''#>prepRepo</option>
<option value="createrepo" #if $method == 'createrepo' then 'selected="selected"' else ''#>createrepo</option>
<option value="dependantTask" #if $method == 'dependantTask' then 'selected="selected"' else ''#>dependantTask</option>
<option value="chainbuild" #if $method == 'chainbuild' then 'selected="selected"' else ''#>chainbuild</option>
<option value="waitrepo" #if $method == 'waitrepo' then 'selected="selected"' else ''#>waitrepo</option>
#for $task_type in $alltasks
<option value="$task_type" #if $method == $task_type then 'selected="selected"' else ''#>$task_type</option>
#end for
</select>
</td><td>
<strong>View</strong>:

View file

@ -437,3 +437,7 @@ span#loginInfo {
font-size: medium;
white-space: pre;
}
.error {
color: red;
}