view MoinMoin/auth/smb_mount.py @ 1414:614005b5edb3

fixed some .format() unicode issues, partially fixing bug #124
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Sat, 07 Jul 2012 20:22:21 +0200
parents 4ac437141bbe
children 384555088cab
line wrap: on
line source
# Copyright: 2006-2008 MoinMoin:ThomasWaldmann
# Copyright: 2007 MoinMoin:JohannesBerg
# License: GNU GPL v2 (or any later version), see LICENSE.txt for details.

"""
    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.
"""


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
        **kw
        ):
        super(SMBMount, self).__init__(**kw)
        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, username, password, login):
        logging.debug("login={0} logout={1}: got name={2!r}".format(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"
        else:
            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:
            try:
                if not os.path.exists(mountpoint):
                    os.makedirs(mountpoint) # the dir containing the mountpoint must be writeable for us!
            except OSError:
                pass
            env['PASSWD'] = password.encode(self.coding)
        subprocess.call(cmd.encode(self.coding), env=env, shell=True)

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

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