non text mime type payloads can be double base64 encoded

Bug #874342 reported by Mat Lowery
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
cloud-init
Fix Released
Medium
Scott Moser

Bug Description

I created a part handler to handle application/octet-stream types. In order to get the true payload, I had to base64 decode twice. The first encode happens because I used write-mime-multipart. The second encode seems to happen in UserDataHandler.parts2mime. Am I doing something wrong or should this second encode not be performed?

Related branches

Revision history for this message
Mat Lowery (mlowery) wrote :

#part-handler

import base64

def list_types():
    return(["application/octet-stream"])

def handle_part(data,ctype,filename,payload):
    if ctype == "__end__" or ctype == "__begin__": return
    if ctype == "application/octet-stream":
        stream = "%s/%s" % ('/var/lib/cloud/instance/scripts',filename)
        f = open(stream, 'wb')
        f.write(base64.b64decode(base64.b64decode(payload)))
        f.close()

Revision history for this message
Scott Moser (smoser) wrote :

Thanks for opening this bug, sorry it took me so long to get to it.
binary payload is definitely not handled well.

if the "part" came from an actual mime multipart (as you've done) with base64 encoded payload, then it would get doubly encoded. If it came from a include of a url, then it would be called 'text' as the type, yet would contain binary payload.

Very inconsistent.

I think i'd like to get to the point where we make a reasonable attempt to pass raw content to the part handler (ie, decoded) if there is an indication that the source was base64 encoded.

I'm not sure how to handle backwards compability though. For example, if I fix this correctly, then I break your part handler above.

Changed in cloud-init:
assignee: nobody → Scott Moser (smoser)
importance: Undecided → Medium
status: New → Confirmed
Scott Moser (smoser)
Changed in cloud-init:
status: Confirmed → In Progress
Revision history for this message
Scott Moser (smoser) wrote :

ok. I just tested that part-handler are now getting "raw" payload if they encoded with base64 and set the content type encoding to 'base64'.

I tested just now like this:
$ write-mime-multipart --gzip -o out.gz part-handler /bin/true:application/octet-stream /etc/passwd:text/plain /bin/sleep:application/octet-stream

where part-handler has:

#part-handler
import base64
def list_types():
    return(["application/octet-stream"])
def handle_part(data,ctype,filename,payload):
    if ctype == "__end__" or ctype == "__begin__": return
    if ctype == "application/octet-stream":
        stream = "%s/%s" % ('/tmp/',filename)
        f = open(stream, 'wb')
        f.write(payload)
        f.close()

The result is that there are /tmp/sleep and /tmp/true with content as they should have.

So, to be clear, this will break part-handlers that were expecting the base64 double encoding.

Scott Moser (smoser)
Changed in cloud-init:
status: In Progress → Fix Committed
Scott Moser (smoser)
Changed in cloud-init:
status: Fix Committed → Fix Released
Revision history for this message
James Falcon (falcojr) wrote :
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.