Ticket #7495: sagenb-7495.patch

File sagenb-7495.patch, 4.0 KB (added by was, 12 years ago)
  • sagenb/notebook/twist.py

    # HG changeset patch
    # User William Stein <wstein@gmail.com>
    # Date 1258683500 28800
    # Node ID 46571d007ab83b8e75a7454183f170d9127e0b33
    # Parent  db20f1bc4eab2f6741401fd44c382cfa5bedd199
    trac 7495 -- 7495 -- notebook: fix massive security vulnerability and get rid of all possible "internal server errors" when doing "Data --> Upload or attach file"
    
    diff -r db20f1bc4eab -r 46571d007ab8 sagenb/notebook/twist.py
    a b  
    128128############################
    129129# An error message
    130130############################
    131 def message(msg, cont=None):
     131def message(msg, cont='/'):
    132132    template_dict = {'msg': msg, 'cont': cont}
    133133    return template(os.path.join('html', 'error_message.html'),
    134134                    **template_dict)
     
    562562        if ctx.args.has_key('nameField'):
    563563            name = ctx.args['nameField'][0].strip()
    564564
     565        if not ctx.args.has_key('urlField'):
     566            return HTMLResponse(stream=message('Error uploading file (missing urlField arg).','/'))
    565567        url = ctx.args['urlField'][0].strip()
    566568
    567569        if not name:
     570            if not ctx.files.has_key('fileField'):
     571                return HTMLResponse(stream=message('Error uploading file (missing fileField file).','/'))
    568572            name = ctx.files['fileField'][0][0]
    569573
    570574        if not name:
    571575            name = newfield
    572576
    573577        if url and not name:
    574             name = os.path.split(url)[-1]
     578            name = url.split('/')[-1]
    575579
     580        # The next line makes sure that name is plain filename,
     581        # so that dest below is a file in the data directory.  See
     582        # trac 7495 for why this is critically important.
     583        name = os.path.split(name)[-1]
     584        if not name:
     585            return HTMLResponse(stream=message('Error uploading file (missing filename).','/'))
    576586        dest = os.path.join(self.worksheet.data_directory(), name)
    577587        if os.path.exists(dest):
     588            if not os.path.isfile(dest):
     589                return HTMLResponse(stream=message('Suspicious filename "%s" encountered uploading file.'%name,'/'))
    578590            os.unlink(dest)
     591           
    579592        response = http.RedirectResponse('/home/'+self.worksheet.filename() + '/datafile?name=%s'%name)
    580593
    581594        if url != '':
    582             #Here we use twisted's downloadPage function which
    583             #returns a deferred object.  We return the deferred to the server,
    584             #and it will wait until the download has finished while
    585             #still serving other requests.  At the end of the deferred
    586             #callback chain should be the response that we wanted to return.
     595            # Here we use twisted's downloadPage function which
     596            # returns a deferred object.  We return the deferred to the server,
     597            # and it will wait until the download has finished while
     598            # still serving other requests.  At the end of the deferred
     599            # callback chain should be the response that we wanted to return.
    587600            from twisted.web.client import downloadPage
    588601
    589             #The callback just returns the response
     602            # The callback just returns the response
    590603            def callback(result):
    591604                return response
    592 
     605            def errback(result):
     606                msg = "There was an error uploading '%s' (please recheck the URL)."%url
     607                return HTMLResponse(stream=message(msg,'/'))
    593608            d = downloadPage(url, dest)
    594609            d.addCallback(callback)
     610            d.addErrback(errback)
    595611            return d
    596612        elif newfield:
    597613            if os.path.exists(dest): os.unlink(dest)
    598614            open(dest,'w').close()
    599615            return response
    600616        else:
     617            if not ctx.files.has_key('fileField'):
     618                return HTMLResponse(stream=message('Error uploading file (missing fileField file).','/'))
    601619            f = file(dest,'wb')
    602620            f.write(ctx.files['fileField'][0][2].read())
    603621            f.close()