view MoinMoin/auth/ @ 5910:7e7e1cbb9d3f

security: fix remote code execution vulnerability in twikidraw/anywikidraw actions We have wikiutil.taintfilename() to make user supplied filenames safe, so that they can't contain any "special" characters like path separators, etc. It is used at many places in moin, but wasn't used here. :|
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Sat, 29 Dec 2012 15:05:29 +0100
parents 8a3c0c726d66
line wrap: on
line source
# -*- coding: iso-8859-1 -*-
    MoinMoin - auth plugin for (un)mounting a smb share

    (u)mount a SMB server's share for username (using username/password for
    authentication at the SMB server). This can be used if you need access
    to files on some share via the wiki, but needs more code to be useful.

    @copyright: 2006-2008 MoinMoin:ThomasWaldmann
                2007 MoinMoin:JohannesBerg
    @license: GNU GPL, see COPYING for details.

from MoinMoin import log
logging = log.getLogger(__name__)

from MoinMoin.auth import BaseAuth, CancelLogin, ContinueLogin

class SMBMount(BaseAuth):
    """ auth plugin for (un)mounting an smb share,
        this is a wrapper around mount.cifs -o <options> //server/share mountpoint

        See man mount.cifs for details.
    def __init__(self,
        server, # mount.cifs //server/share
        share, # mount.cifs //server/share
        mountpoint_fn, # function of username to determine the mountpoint, e.g.:
                       # lambda username: u'/mnt/wiki/%s' % username
        dir_user, # username to get the uid that is used for mount.cifs -o uid=... (e.g. 'www-data')
        domain, # mount.cifs -o domain=...
        dir_mode='0700', # mount.cifs -o dir_mode=...
        file_mode='0600', # mount.cifs -o file_mode=...
        iocharset='utf-8', # mount.cifs -o iocharset=... (try 'iso8859-1' if default does not work)
        coding='utf-8', # encoding used for username/password/cmdline (try 'iso8859-1' if default does not work)
        log='/dev/null', # logfile for mount.cifs output
        self.server = server
        self.share = share
        self.mountpoint_fn = mountpoint_fn
        self.dir_user = dir_user
        self.domain = domain
        self.dir_mode = dir_mode
        self.file_mode = file_mode
        self.iocharset = iocharset
        self.log = log
        self.coding = coding

    def do_smb(self, request, username, password, login):
        logging.debug("login=%s logout=%s: got name=%s" % (login, not login, username))

        import os, pwd, subprocess
        web_username = self.dir_user
        web_uid = pwd.getpwnam(web_username)[2] # XXX better just use current uid?

        mountpoint = self.mountpoint_fn(username)
        if login:
            cmd = u"sudo mount -t cifs -o user=%(user)s,domain=%(domain)s,uid=%(uid)d,dir_mode=%(dir_mode)s,file_mode=%(file_mode)s,iocharset=%(iocharset)s //%(server)s/%(share)s %(mountpoint)s >>%(log)s 2>&1"
            cmd = u"sudo umount %(mountpoint)s >>%(log)s 2>&1"

        cmd = cmd % {
            'user': username,
            'uid': web_uid,
            'domain': self.domain,
            'server': self.server,
            'share': self.share,
            'mountpoint': mountpoint,
            'dir_mode': self.dir_mode,
            'file_mode': self.file_mode,
            'iocharset': self.iocharset,
            'log': self.log,
        env = os.environ.copy()
        if login:
                if not os.path.exists(mountpoint):
                    os.makedirs(mountpoint) # the dir containing the mountpoint must be writeable for us!
            except OSError:
            env['PASSWD'] = password.encode(self.coding), env=env, shell=True)

    def login(self, request, user_obj, **kw):
        username = kw.get('username')
        password = kw.get('password')
        if user_obj and user_obj.valid:
            self.do_smb(request, username, password, True)
        return ContinueLogin(user_obj)

    def logout(self, request, user_obj, **kw):
        if user_obj and not user_obj.valid:
            self.do_smb(request,, None, False)
        return user_obj, True