Ejemplo n.º 1
0
def xpra_group() -> int:
    if POSIX:
        try:
            groups = os.getgroups()
            group_id = get_group_id(MMAP_GROUP)
            log("xpra_group() group(%s)=%s, groups=%s", MMAP_GROUP, group_id, groups)
            if group_id and group_id in groups:
                return group_id
        except Exception:
            log("xpra_group()", exc_info=True)
    return 0
Ejemplo n.º 2
0
def xpra_group():
    if POSIX:
        try:
            username = os.getgroups()
            groups = get_groups(username)
            if MMAP_GROUP in groups:
                group_id = get_group_id(MMAP_GROUP)
                if group_id >= 0:
                    return group_id
        except Exception:
            log("xpra_group()", exc_info=True)
    return 0
Ejemplo n.º 3
0
def create_unix_domain_socket(sockpath, socket_permissions=0o600):
    #convert this to a umask!
    umask = 0o777 - socket_permissions
    listener = socket.socket(socket.AF_UNIX)
    listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    #bind the socket, using umask to set the correct permissions
    orig_umask = os.umask(umask)
    try:
        listener.bind(sockpath)
    finally:
        os.umask(orig_umask)
    try:
        inode = os.stat(sockpath).st_ino
    except:
        inode = -1
    #set to the "xpra" group if we are a member of it, or if running as root:
    uid = getuid()
    username = get_username_for_uid(uid)
    groups = get_groups(username)
    if uid == 0 or GROUP in groups:
        group_id = get_group_id(GROUP)
        if group_id >= 0:
            try:
                os.lchown(sockpath, -1, group_id)
            except Exception as e:
                log = get_network_logger()
                log.warn("Warning: failed to set '%s' group ownership", GROUP)
                log.warn(" on socket '%s':", sockpath)
                log.warn(" %s", e)
            #don't know why this doesn't work:
            #os.fchown(listener.fileno(), -1, group_id)
    def cleanup_socket():
        log = get_network_logger()
        try:
            cur_inode = os.stat(sockpath).st_ino
        except:
            log.info("socket '%s' already deleted", sockpath)
            return
        delpath = sockpath
        log("cleanup_socket '%s', original inode=%s, new inode=%s", sockpath,
            inode, cur_inode)
        if cur_inode == inode:
            log.info("removing socket %s", delpath)
            try:
                os.unlink(delpath)
            except:
                pass

    return listener, cleanup_socket
Ejemplo n.º 4
0
 def create_system_dir(self, sps):
     if not POSIX or OSX or not sps:
         return
     xpra_group_id = get_group_id(SOCKET_DIR_GROUP)
     if sps.startswith("/run/xpra") or sps.startswith("/var/run/xpra"):
         #create the directory and verify its permissions
         #which should have been set correctly by tmpfiles.d,
         #but may have been set wrong if created by systemd's socket activation instead
         d = sps.split("/xpra")[0] + "/xpra"
         try:
             if os.path.exists(d):
                 stat = os.stat(d)
                 mode = stat.st_mode
                 if (mode & SOCKET_DIR_MODE) != SOCKET_DIR_MODE:
                     log.warn("Warning: invalid permissions on '%s' : %s",
                              d, oct(mode))
                     mode = mode | SOCKET_DIR_MODE
                     log.warn(" changing to %s", oct(mode))
                     os.chmod(d, mode)
                 if xpra_group_id >= 0 and stat.st_gid != xpra_group_id:
                     import grp
                     group = grp.getgrgid(stat.st_gid)[0]
                     log.warn("Warning: invalid group on '%s': %s", d,
                              group)
                     log.warn(" changing to '%s'", SOCKET_DIR_GROUP)
                     os.lchown(d, stat.st_uid, xpra_group_id)
             else:
                 log.info(
                     "creating '%s' with permissions %s and group '%s'", d,
                     oct(SOCKET_DIR_MODE), SOCKET_DIR_GROUP)
                 with umask_context(0):
                     os.mkdir(d, SOCKET_DIR_MODE)
                 stat = os.stat(d)
                 if xpra_group_id >= 0 and stat.st_gid != xpra_group_id:
                     os.lchown(d, stat.st_uid, xpra_group_id)
             mode = os.stat(d).st_mode
             log("%s permissions: %s", d, oct(mode))
         except OSError as e:
             log("create_system_dir()", exc_info=True)
             log.error(
                 "Error: failed to create or change the permissions on '%s':",
                 d)
             log.error(" %s", e)
Ejemplo n.º 5
0
 def check_peercred(self, connection, uids="", gids="", allow_owner=False):
     allow_uids = allow_gids = None
     if uids or allow_owner:
         allow_uids = []
         if allow_owner:
             allow_uids.append(getuid())
         for x in uids.split(":"):
             if not x.strip():
                 continue
             x = osexpand(x.strip())
             try:
                 allow_uids.append(int(x))
             except ValueError:
                 import pwd  #pylint: disable=import-outside-toplevel
                 try:
                     pw = pwd.getpwnam(x)
                     allow_uids.append(pw.pw_uid)
                 except KeyError:
                     log.warn("Warning: unknown username '%s'", x)
         log("peercred: allow_uids(%s)=%s", uids, allow_uids)
     if gids:
         allow_gids = []
         for x in gids.split(":"):
             if not x.strip():
                 continue
             x = osexpand(x.strip())
             try:
                 allow_gids.append(int(x))
             except ValueError:
                 gid = get_group_id(x)
                 if gid >= 0:
                     allow_gids.append(gid)
                 else:
                     log.warn("Warning: unknown group '%s'", x)
         log("peercred: allow_gids(%s)=%s", gids, allow_gids)
     self.do_check_peercred(connection, allow_uids, allow_gids)
Ejemplo n.º 6
0
def create_unix_domain_socket(sockpath,
                              mmap_group=False,
                              socket_permissions="600"):
    if mmap_group:
        #when using the mmap group option, use '660'
        umask = 0o117
    else:
        #parse octal mode given as config option:
        try:
            if type(socket_permissions) == int:
                sperms = socket_permissions
            else:
                #assume octal string:
                sperms = int(socket_permissions, 8)
            assert sperms >= 0 and sperms <= 0o777
        except ValueError:
            raise ValueError(
                "invalid socket permissions (must be an octal number): '%s'" %
                socket_permissions)
        #now convert this to a umask!
        umask = 0o777 - sperms
    listener = socket.socket(socket.AF_UNIX)
    listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    #bind the socket, using umask to set the correct permissions
    orig_umask = os.umask(umask)
    try:
        listener.bind(sockpath)
    finally:
        os.umask(orig_umask)
    try:
        inode = os.stat(sockpath).st_ino
    except:
        inode = -1
    #set to the "xpra" group if we are a member of it, or if running as root:
    uid = getuid()
    username = get_username_for_uid(uid)
    groups = get_groups(username)
    if uid == 0 or GROUP in groups:
        group_id = get_group_id(GROUP)
        if group_id >= 0:
            try:
                os.lchown(sockpath, -1, group_id)
            except Exception as e:
                log = get_network_logger()
                log.warn("Warning: failed to set '%s' group ownership", GROUP)
                log.warn(" on socket '%s':", sockpath)
                log.warn(" %s", e)
            #don't know why this doesn't work:
            #os.fchown(listener.fileno(), -1, group_id)
    def cleanup_socket():
        log = get_network_logger()
        try:
            cur_inode = os.stat(sockpath).st_ino
        except:
            log.info("socket '%s' already deleted", sockpath)
            return
        delpath = sockpath
        log("cleanup_socket '%s', original inode=%s, new inode=%s", sockpath,
            inode, cur_inode)
        if cur_inode == inode:
            log.info("removing socket %s", delpath)
            try:
                os.unlink(delpath)
            except:
                pass

    return listener, cleanup_socket
Ejemplo n.º 7
0
def setup_local_sockets(bind,
                        socket_dir,
                        socket_dirs,
                        display_name,
                        clobber,
                        mmap_group="auto",
                        socket_permissions="600",
                        username="",
                        uid=0,
                        gid=0):
    log = get_network_logger()
    log("setup_local_sockets%s",
        (bind, socket_dir, socket_dirs, display_name, clobber, mmap_group,
         socket_permissions, username, uid, gid))
    if not bind:
        return {}
    if not socket_dir and (not socket_dirs or
                           (len(socket_dirs) == 1 and not socket_dirs[0])):
        if WIN32:
            socket_dirs = [""]
        else:
            raise InitExit(
                EXIT_SOCKET_CREATION_ERROR,
                "at least one socket directory must be set to use unix domain sockets"
            )
    from xpra.platform.dotxpra import DotXpra, norm_makepath
    dotxpra = DotXpra(socket_dir or socket_dirs[0], socket_dirs, username, uid,
                      gid)
    if display_name is not None and not WIN32:
        display_name = normalize_local_display_name(display_name)
    defs = {}
    try:
        sockpaths = {}
        log("setup_local_sockets: bind=%s, dotxpra=%s", bind, dotxpra)
        for b in bind:
            if b in ("none", ""):
                continue
            parts = b.split(",")
            sockpath = parts[0]
            options = {}
            if len(parts) == 2:
                options = parse_simple_dict(parts[1])
            if sockpath == "auto":
                assert display_name is not None
                for sockpath in dotxpra.norm_socket_paths(display_name):
                    sockpaths[sockpath] = options
                log("sockpaths(%s)=%s (uid=%i, gid=%i)", display_name,
                    sockpaths, uid, gid)
            else:
                sockpath = dotxpra.osexpand(sockpath)
                if os.path.isabs(sockpath):
                    pass
                elif sockpath.endswith("/") or (os.path.exists(sockpath)
                                                and os.path.isdir(sockpath)):
                    assert display_name is not None
                    sockpath = os.path.abspath(sockpath)
                    if not os.path.exists(sockpath):
                        os.makedirs(sockpath)
                    sockpath = norm_makepath(sockpath, display_name)
                else:
                    sockpath = dotxpra.socket_path(sockpath)
                sockpaths[sockpath] = options
            assert sockpaths, "no socket paths to try for %s" % b
        #expand and remove duplicate paths:
        tmp = {}
        for tsp, options in sockpaths.items():
            sockpath = dotxpra.osexpand(tsp)
            if sockpath in tmp:
                log.warn("Warning: skipping duplicate bind path %s", sockpath)
                continue
            tmp[sockpath] = options
        sockpaths = tmp
        log("sockpaths=%s", sockpaths)
        #create listeners:
        if WIN32:
            from xpra.platform.win32.namedpipes.listener import NamedPipeListener
            from xpra.platform.win32.dotxpra import PIPE_PATH
            for sockpath, options in sockpaths.items():
                npl = NamedPipeListener(sockpath)
                ppath = sockpath
                if ppath.startswith(PIPE_PATH):
                    ppath = ppath[len(PIPE_PATH):]
                log.info("created named pipe '%s'", ppath)
                defs[("named-pipe", npl, sockpath, npl.stop)] = options
        else:

            def checkstate(sockpath, state):
                if state not in (DotXpra.DEAD, DotXpra.UNKNOWN):
                    if state == DotXpra.INACCESSIBLE:
                        raise InitException(
                            "An xpra server is already running at %s\n" %
                            (sockpath, ))
                    raise InitExit(
                        EXIT_SERVER_ALREADY_EXISTS,
                        "You already have an xpra server running at %s\n"
                        "  (did you want 'xpra upgrade'?)" % (sockpath, ))

            #remove exisiting sockets if clobber is set,
            #otherwise verify there isn't a server already running
            #and create the directories for the sockets:
            unknown = []
            for sockpath in sockpaths:
                if clobber and os.path.exists(sockpath):
                    os.unlink(sockpath)
                else:
                    state = dotxpra.get_server_state(sockpath, 1)
                    log("state(%s)=%s", sockpath, state)
                    checkstate(sockpath, state)
                    if state == dotxpra.UNKNOWN:
                        unknown.append(sockpath)
                d = os.path.dirname(sockpath)
                try:
                    kwargs = {}
                    if d in ("/var/run/xpra", "/run/xpra"):
                        #this is normally done by tmpfiles.d,
                        #but we may need to do it ourselves in some cases:
                        kwargs["mode"] = SOCKET_DIR_MODE
                        xpra_gid = get_group_id(SOCKET_DIR_GROUP)
                        if xpra_gid > 0:
                            kwargs["gid"] = xpra_gid
                    log("creating sockdir=%s, kwargs=%s" % (d, kwargs))
                    dotxpra.mksockdir(d, **kwargs)
                    log("%s permission mask: %s", d, oct(os.stat(d).st_mode))
                except Exception as e:
                    log.warn("Warning: failed to create socket directory '%s'",
                             d)
                    log.warn(" %s", e)
                    del e
            #wait for all the unknown ones:
            log("sockets in unknown state: %s", unknown)
            if unknown:
                #re-probe them using threads so we can do them in parallel:
                threads = []

                def timeout_probe(sockpath):
                    #we need a loop because "DEAD" sockets may return immediately
                    #(ie: when the server is starting up)
                    start = monotonic_time()
                    while monotonic_time() - start < WAIT_PROBE_TIMEOUT:
                        state = dotxpra.get_server_state(
                            sockpath, WAIT_PROBE_TIMEOUT)
                        log("timeout_probe() get_server_state(%s)=%s",
                            sockpath, state)
                        if state not in (DotXpra.UNKNOWN, DotXpra.DEAD):
                            break
                        sleep(1)

                log.warn(
                    "Warning: some of the sockets are in an unknown state:")
                for sockpath in unknown:
                    log.warn(" %s", sockpath)
                    t = start_thread(timeout_probe,
                                     "probe-%s" % sockpath,
                                     daemon=True,
                                     args=(sockpath, ))
                    threads.append(t)
                log.warn(
                    " please wait as we allow the socket probing to timeout")
                #wait for all the threads to do their job:
                for t in threads:
                    t.join(WAIT_PROBE_TIMEOUT + 1)
            if sockpaths:
                #now we can re-check quickly:
                #(they should all be DEAD or UNKNOWN):
                for sockpath in sockpaths:
                    state = dotxpra.get_server_state(sockpath, 1)
                    log("state(%s)=%s", sockpath, state)
                    checkstate(sockpath, state)
                    try:
                        if os.path.exists(sockpath):
                            os.unlink(sockpath)
                    except OSError:
                        pass
                #socket permissions:
                if mmap_group.lower() in TRUE_OPTIONS:
                    #when using the mmap group option, use '660'
                    sperms = 0o660
                else:
                    #parse octal mode given as config option:
                    try:
                        if isinstance(socket_permissions, int):
                            sperms = socket_permissions
                        else:
                            #assume octal string:
                            sperms = int(socket_permissions, 8)
                        assert 0 <= sperms <= 0o777, "invalid socket permission value %s" % oct(
                            sperms)
                    except ValueError:
                        raise ValueError("invalid socket permissions " +
                                         "(must be an octal number): '%s'" %
                                         socket_permissions) from None
                #now try to create all the sockets:
                for sockpath, options in sockpaths.items():
                    #create it:
                    try:
                        sock, cleanup_socket = create_unix_domain_socket(
                            sockpath, sperms)
                        log.info("created unix domain socket '%s'", sockpath)
                        defs[("unix-domain", sock, sockpath,
                              cleanup_socket)] = options
                    except Exception as e:
                        handle_socket_error(sockpath, sperms, e)
                        del e
    except Exception:
        for sock, cleanup_socket in defs.items():
            try:
                cleanup_socket()
            except Exception as e:
                log.error("Error cleaning up socket %s:", sock)
                log.error(" %s", e)
                del e
        raise
    return defs
Ejemplo n.º 8
0
 def __init__(self, username, **kwargs):
     log("peercred.Authenticator(%s, %s)", username, kwargs)
     if not POSIX:
         log.warn("Warning: peercred authentication is not supported on %s",
                  os.name)
         return
     self.uid = -1
     self.gid = -1
     self.peercred_check = False
     connection = kwargs.get("connection", None)
     uids = kwargs.pop("uid", None)
     gids = kwargs.pop("gid", None)
     allow_uids = None
     allow_gids = None
     if uids:
         allow_uids = []
         for x in uids.split(","):
             x = osexpand(x.strip())
             try:
                 allow_uids.append(int(x))
             except ValueError:
                 import pwd
                 try:
                     pw = pwd.getpwnam(x)
                     uids.append(pw.pw_uid)
                 except KeyError:
                     log.warn("Warning: unknown username '%s'", x)
         log("peercred: allow_uids(%s)=%s", uids, allow_uids)
     if gids:
         allow_gids = []
         for x in gids.split(","):
             x = osexpand(x.strip())
             try:
                 allow_gids.append(int(x))
             except ValueError:
                 gid = get_group_id(x)
                 if gid >= 0:
                     allow_gids.append(gid)
                 else:
                     log.warn("Warning: unknown group '%s'", x)
         log("peercred: allow_gids(%s)=%s", gids, allow_gids)
     try:
         from xpra.net.bytestreams import SocketConnection
         if connection and isinstance(connection, SocketConnection):
             sock = connection._socket
             peercred = get_peercred(sock)
             log("get_peercred(%s)=%s", sock, peercred)
             if not peercred:
                 log.warn("Warning: failed to get peer credentials on %s",
                          sock)
                 return
             _, uid, gid = peercred
             if allow_uids is not None and uid not in allow_uids:
                 log.warn("Warning: peercred access denied,")
                 log.warn(" uid %i is not in the whitelist: %s", uid,
                          csv(allow_uids))
             elif allow_gids is not None and gid not in allow_gids:
                 log.warn("Warning: peercred access denied,")
                 log.warn(" gid %i is not in the whitelist: %s", gid,
                          csv(allow_gids))
             else:
                 self.peercred_check = True
                 self.uid = uid
                 self.gid = gid
         else:
             log(
                 "peercred: invalid connection '%s' (not a socket connection)",
                 connection)
     except Exception as e:
         log.error("Error: cannot get peer uid")
         log.error(" %s", e)
     SysAuthenticator.__init__(self, username, **kwargs)
Ejemplo n.º 9
0
def init_client_mmap(mmap_group=None,
                     socket_filename=None,
                     size=128 * 1024 * 1024,
                     filename=None):
    """
        Initializes an mmap area, writes the token in it and returns:
            (success flag, mmap_area, mmap_size, temp_file, mmap_filename)
        The caller must keep hold of temp_file to ensure it does not get deleted!
        This is used by the client.
    """
    def rerr():
        return False, False, None, 0, None, None

    log("init_mmap%s", (mmap_group, socket_filename, size, filename))
    mmap_filename = filename
    mmap_temp_file = None
    delete = True

    def validate_size(size):
        assert size >= 64 * 1024 * 1024, "mmap size is too small: %sB (minimum is 64MB)" % std_unit(
            size)
        assert size <= 4 * 1024 * 1024 * 1024, "mmap is too big: %sB (maximum is 4GB)" % std_unit(
            size)

    try:
        import mmap
        unit = max(4096, mmap.PAGESIZE)
        #add 8 bytes for the mmap area control header zone:
        mmap_size = roundup(size + 8, unit)
        if WIN32:
            validate_size(mmap_size)
            if not filename:
                from xpra.os_util import get_hex_uuid
                filename = "xpra-%s" % get_hex_uuid()
            mmap_filename = filename
            mmap_area = mmap.mmap(0, mmap_size, filename)
            #not a real file:
            delete = False
            mmap_temp_file = None
        else:
            assert POSIX
            if filename:
                if os.path.exists(filename):
                    fd = os.open(filename, os.O_EXCL | os.O_RDWR)
                    mmap_size = os.path.getsize(mmap_filename)
                    validate_size(mmap_size)
                    #mmap_size = 4*1024*1024    #size restriction needed with ivshmem
                    delete = False
                    log.info("Using existing mmap file '%s': %sMB",
                             mmap_filename, mmap_size // 1024 // 1024)
                else:
                    validate_size(mmap_size)
                    import errno
                    flags = os.O_CREAT | os.O_EXCL | os.O_RDWR
                    try:
                        fd = os.open(filename, flags)
                        mmap_temp_file = None  #os.fdopen(fd, 'w')
                        mmap_filename = filename
                    except OSError as e:
                        if e.errno == errno.EEXIST:
                            log.error(
                                "Error: the mmap file '%s' already exists",
                                filename)
                            return rerr()
                        raise
            else:
                validate_size(mmap_size)
                import tempfile
                from xpra.platform.paths import get_mmap_dir
                mmap_dir = get_mmap_dir()
                subs = os.environ.copy()
                subs.update({
                    "UID": os.getuid(),
                    "GID": os.getgid(),
                    "PID": os.getpid(),
                })
                mmap_dir = shellsub(mmap_dir, subs)
                if mmap_dir and not os.path.exists(mmap_dir):
                    os.mkdir(mmap_dir, 0o700)
                if not mmap_dir or not os.path.exists(mmap_dir):
                    raise Exception("mmap directory %s does not exist!" %
                                    mmap_dir)
                #create the mmap file, the mkstemp that is called via NamedTemporaryFile ensures
                #that the file is readable and writable only by the creating user ID
                try:
                    temp = tempfile.NamedTemporaryFile(prefix="xpra.",
                                                       suffix=".mmap",
                                                       dir=mmap_dir)
                except OSError as e:
                    log.error("Error: cannot create mmap file:")
                    log.error(" %s", e)
                    return rerr()
                #keep a reference to it so it does not disappear!
                mmap_temp_file = temp
                mmap_filename = temp.name
                fd = temp.file.fileno()
            #set the group permissions and gid if the mmap-group option is specified
            mmap_group = (mmap_group or "")
            if POSIX and mmap_group and mmap_group not in FALSE_OPTIONS:
                group_id = None
                if mmap_group == "SOCKET":
                    group_id = get_socket_group(socket_filename)
                elif mmap_group.lower() == "auto":
                    group_id = xpra_group()
                    if not group_id and socket_filename:
                        group_id = get_socket_group(socket_filename)
                elif mmap_group.lower() in TRUE_OPTIONS:
                    log.info("parsing legacy mmap-group value '%s' as 'auto'",
                             mmap_group)
                    log.info(" please update your configuration")
                    group_id = xpra_group() or get_socket_group(
                        socket_filename)
                else:
                    group_id = get_group_id(mmap_group)
                if group_id > 0:
                    log("setting mmap file %s to group id=%i", mmap_filename,
                        group_id)
                    try:
                        os.fchown(fd, -1, group_id)
                    except OSError as e:
                        log("fchown(%i, %i, %i) on %s",
                            fd,
                            -1,
                            group_id,
                            mmap_filename,
                            exc_info=True)
                        log.error(
                            "Error: failed to change group ownership of mmap file to '%s':",
                            mmap_group)
                        log.error(" %s", e)
                    from stat import S_IRUSR, S_IWUSR, S_IRGRP, S_IWGRP
                    os.fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)
            log("using mmap file %s, fd=%s, size=%s", mmap_filename, fd,
                mmap_size)
            os.lseek(fd, mmap_size - 1, os.SEEK_SET)
            assert os.write(fd, b'\x00')
            os.lseek(fd, 0, os.SEEK_SET)
            mmap_area = mmap.mmap(fd, length=mmap_size)
        return True, delete, mmap_area, mmap_size, mmap_temp_file, mmap_filename
    except Exception as e:
        log("failed to setup mmap: %s", e, exc_info=True)
        log.error("Error: mmap setup failed:")
        log.error(" %s", e)
        clean_mmap(mmap_filename)
        return rerr()
Ejemplo n.º 10
0
def setup_local_sockets(bind,
                        socket_dir,
                        socket_dirs,
                        display_name,
                        clobber,
                        mmap_group=False,
                        socket_permissions="600",
                        username="",
                        uid=0,
                        gid=0):
    if not bind:
        return []
    if not socket_dir and (not socket_dirs or
                           (len(socket_dirs) == 1 and not socket_dirs[0])):
        if WIN32:
            socket_dirs = [""]
        else:
            raise InitException(
                "at least one socket directory must be set to use unix domain sockets"
            )
    dotxpra = DotXpra(socket_dir or socket_dirs[0], socket_dirs, username, uid,
                      gid)
    display_name = normalize_local_display_name(display_name)
    log = get_network_logger()
    defs = []
    try:
        sockpaths = []
        log("setup_local_sockets: bind=%s", bind)
        for b in bind:
            sockpath = b
            if b == "none" or b == "":
                continue
            elif b == "auto":
                sockpaths += dotxpra.norm_socket_paths(display_name)
                log("sockpaths(%s)=%s (uid=%i, gid=%i)", display_name,
                    sockpaths, uid, gid)
            else:
                sockpath = dotxpra.osexpand(b)
                if b.endswith("/") or (os.path.exists(sockpath)
                                       and os.path.isdir(sockpath)):
                    sockpath = os.path.abspath(sockpath)
                    if not os.path.exists(sockpath):
                        os.makedirs(sockpath)
                    sockpath = norm_makepath(sockpath, display_name)
                elif os.path.isabs(b):
                    sockpath = b
                else:
                    sockpath = dotxpra.socket_path(b)
                sockpaths += [sockpath]
            assert sockpaths, "no socket paths to try for %s" % b
        #expand and remove duplicate paths:
        tmp = []
        for tsp in sockpaths:
            sockpath = dotxpra.osexpand(tsp)
            if sockpath in tmp:
                log.warn("Warning: skipping duplicate bind path %s", sockpath)
                continue
            tmp.append(sockpath)
        sockpaths = tmp
        #create listeners:
        if WIN32:
            from xpra.platform.win32.namedpipes.listener import NamedPipeListener
            for sockpath in sockpaths:
                npl = NamedPipeListener(sockpath)
                log.info("created named pipe: %s", sockpath)
                defs.append((("named-pipe", npl, sockpath), npl.stop))
        else:

            def checkstate(sockpath, state):
                if state not in (DotXpra.DEAD, DotXpra.UNKNOWN):
                    if state == DotXpra.INACCESSIBLE:
                        raise InitException(
                            "An xpra server is already running at %s\n" %
                            (sockpath, ))
                    raise InitException(
                        "You already have an xpra server running at %s\n"
                        "  (did you want 'xpra upgrade'?)" % (sockpath, ))

            #remove exisiting sockets if clobber is set,
            #otherwise verify there isn't a server already running
            #and create the directories for the sockets:
            unknown = []
            for sockpath in sockpaths:
                if clobber and os.path.exists(sockpath):
                    os.unlink(sockpath)
                else:
                    state = dotxpra.get_server_state(sockpath, 1)
                    log("state(%s)=%s", sockpath, state)
                    checkstate(sockpath, state)
                    if state == dotxpra.UNKNOWN:
                        unknown.append(sockpath)
                d = os.path.dirname(sockpath)
                try:
                    kwargs = {}
                    if getuid(
                    ) == 0 and d == "/var/run/xpra" or d == "/run/xpra":
                        #this is normally done by tmpfiles.d,
                        #but we may need to do it ourselves in some cases:
                        kwargs = {"mode": 0o775}
                        xpra_gid = get_group_id("xpra")
                        if xpra_gid > 0:
                            kwargs["gid"] = xpra_gid
                    log("creating sockdir=%s, kwargs=%s" % (d, kwargs))
                    dotxpra.mksockdir(d, **kwargs)
                except Exception as e:
                    log.warn("Warning: failed to create socket directory '%s'",
                             d)
                    log.warn(" %s", e)
                    del e
            #wait for all the unknown ones:
            log("sockets in unknown state: %s", unknown)
            if unknown:
                #re-probe them using threads so we can do them in parallel:
                from time import sleep
                from xpra.make_thread import start_thread
                threads = []

                def timeout_probe(sockpath):
                    #we need a loop because "DEAD" sockets may return immediately
                    #(ie: when the server is starting up)
                    start = monotonic_time()
                    while monotonic_time() - start < WAIT_PROBE_TIMEOUT:
                        state = dotxpra.get_server_state(
                            sockpath, WAIT_PROBE_TIMEOUT)
                        log("timeout_probe() get_server_state(%s)=%s",
                            sockpath, state)
                        if state not in (DotXpra.UNKNOWN, DotXpra.DEAD):
                            break
                        sleep(1)

                log.warn(
                    "Warning: some of the sockets are in an unknown state:")
                for sockpath in unknown:
                    log.warn(" %s", sockpath)
                    t = start_thread(timeout_probe,
                                     "probe-%s" % sockpath,
                                     daemon=True,
                                     args=(sockpath, ))
                    threads.append(t)
                log.warn(
                    " please wait as we allow the socket probing to timeout")
                #wait for all the threads to do their job:
                for t in threads:
                    t.join(WAIT_PROBE_TIMEOUT + 1)
            if sockpaths:
                #now we can re-check quickly:
                #(they should all be DEAD or UNKNOWN):
                for sockpath in sockpaths:
                    state = dotxpra.get_server_state(sockpath, 1)
                    log("state(%s)=%s", sockpath, state)
                    checkstate(sockpath, state)
                    try:
                        if os.path.exists(sockpath):
                            os.unlink(sockpath)
                    except:
                        pass
                #socket permissions:
                if mmap_group:
                    #when using the mmap group option, use '660'
                    sperms = 0o660
                else:
                    #parse octal mode given as config option:
                    try:
                        if type(socket_permissions) == int:
                            sperms = socket_permissions
                        else:
                            #assume octal string:
                            sperms = int(socket_permissions, 8)
                        assert sperms >= 0 and sperms <= 0o777, "invalid socket permission value %s" % oct(
                            sperms)
                    except ValueError:
                        raise ValueError(
                            "invalid socket permissions (must be an octal number): '%s'"
                            % socket_permissions)
                #now try to create all the sockets:
                for sockpath in sockpaths:
                    #create it:
                    try:
                        sock, cleanup_socket = create_unix_domain_socket(
                            sockpath, sperms)
                        log.info("created unix domain socket: %s", sockpath)
                        defs.append(
                            (("unix-domain", sock, sockpath), cleanup_socket))
                    except Exception as e:
                        handle_socket_error(sockpath, sperms, e)
                        del e
    except:
        for sock, cleanup_socket in defs:
            try:
                cleanup_socket()
            except Exception as e:
                log.error("Error cleaning up socket %s:", sock)
                log.error(" %s", e)
                del e
        defs = []
        raise
    return defs