예제 #1
0
def LocalGroup(uname=None):
    "Creates a local group, adds some members, deletes them, then removes the group"
    level = 3
    if uname is None: uname = win32api.GetUserName()
    if uname.find("\\") < 0:
        uname = win32api.GetDomainName() + "\\" + uname
    group = 'python_test_group'
    # delete the group if it already exists
    try:
        win32net.NetLocalGroupDel(server, group)
        print "WARNING: existing local group '%s' has been deleted."
    except win32net.error:
        pass
    group_data = {'name': group}
    win32net.NetLocalGroupAdd(server, 1, group_data)
    try:
        u = {'domainandname': uname}
        win32net.NetLocalGroupAddMembers(server, group, level, [u])
        mem, tot, res = win32net.NetLocalGroupGetMembers(server, group, level)
        print "members are", mem
        if mem[0]['domainandname'] != uname:
            print "ERROR: LocalGroup just added %s, but members are %r" % (
                uname, mem)
        # Convert the list of dicts to a list of strings.
        win32net.NetLocalGroupDelMembers(server, group,
                                         [m['domainandname'] for m in mem])
    finally:
        win32net.NetLocalGroupDel(server, group)
    print "Created a local group, added and removed members, then deleted the group"
예제 #2
0
    def preConnect(self, userName: str, protocol: str, ip: str, hostname: str) -> str:
        logger.debug('Pre connect invoked')

        if protocol == 'rdp':  # If connection is not using rdp, skip adding user
            # Well known SSID for Remote Desktop Users
            groupName = win32security.LookupAccountSid(None, win32security.GetBinarySid(REMOTE_USERS_SID))[0]

            useraAlreadyInGroup = False
            resumeHandle = 0
            while True:
                users, _, resumeHandle = win32net.NetLocalGroupGetMembers(None, groupName, 1, resumeHandle, 32768)
                if userName.lower() in [u['name'].lower() for u in users]:
                    useraAlreadyInGroup = True
                    break
                if resumeHandle == 0:
                    break

            if not useraAlreadyInGroup:
                logger.debug('User not in group, adding it')
                self._user = userName
                try:
                    userSSID = win32security.LookupAccountName(None, userName)[0]
                    win32net.NetLocalGroupAddMembers(None, groupName, 0, [{'sid': userSSID}])
                except Exception as e:
                    logger.error('Exception adding user to Remote Desktop Users: {}'.format(e))
            else:
                self._user = None
                logger.debug('User {} already in group'.format(userName))

        return super().preConnect(userName, protocol, ip, hostname)
예제 #3
0
    def groupMember(name_):
        try:
            (users, _, _) = win32net.NetLocalGroupGetMembers(None, name_, 1)

        except win32net.error, e:
            Logger.error("groupMember: '%s'" % (str(e)))
            return None
예제 #4
0
def LocalGroupEnum():
    "Enumerates all the local groups"
    resume = 0
    nmembers = 0
    while 1:
        data, total, resume = win32net.NetLocalGroupEnum(server, 1, resume)
        for group in data:
            verbose("Found group %(name)s:%(comment)s " % group)
            memberresume = 0
            while 1:
                memberdata, total, memberresume = win32net.NetLocalGroupGetMembers(
                    server, group['name'], 2, resume)
                for member in memberdata:
                    # Just for the sake of it, we convert the SID to a username
                    username, domain, type = win32security.LookupAccountSid(
                        server, member['sid'])
                    nmembers = nmembers + 1
                    verbose(" Member %s (%s)" %
                            (username, member['domainandname']))
                if memberresume == 0:
                    break
        if not resume:
            break
    assert nmembers, "Couldnt find a single member in a single group!"
    print "Enumerated all the local groups"
예제 #5
0
def check_admin(username):
    ''' Periodically checks for Admin Privs '''
    global is_admin
    while not is_admin:
        members = win32net.NetLocalGroupGetMembers(None, 'Administrators', 1)
        if username in [record['name'] for record in members[0]]:
            is_admin = True
            break
        time.sleep(5)
예제 #6
0
    def __get_local_groups__(self):
        """
            En prévision de l'avenir.
            Sur une machine qui n'est pas contrôleur de domaine la fonction NetGroupEnum ramène un seul groupe qui
            d'appelle "None".

            On verra plus tard comment traiter ça.
                Un indicateur serveur AD / pas serveur AD ?
                On appelle ça de façon transparente si on se rend compte qu'on n'est pas sur un serveur AD ?
                On ajoute les groupes locaux aux groupes globaux si on est sur un un serveur AD ?
        """
        groups_list = []
        resume = 0
        Enr, Total, resume = win32net.NetLocalGroupEnum(
            self.server, 1, resume, 4096)
        while 1:
            for Champ in Enr:
                group_name = Champ['name'].lower()
                members_list = []
                memberresume = 0
                memberdata, total, memberresume = win32net.NetLocalGroupGetMembers(
                    self.server, group_name, 1, memberresume)

                while 1:
                    for member in memberdata:
                        members_list.append(member['name'].lower())

                    if memberresume <= 0:
                        break

                    memberdata, total, memberresume = win32net.NetLocalGroupGetMembers(
                        self.server, group_name, 1, memberresume)

                members_list.sort()
                groups_list.append([group_name, members_list])

            if resume <= 0:
                break

            Enr, Total, resume = win32net.NetLocalGroupEnum(
                self.server, 1, resume, 4096)

        return groups_list
예제 #7
0
    def preConnect(self, user, protocol):
        logger.debug('Pre connect invoked')
        if protocol != 'rdp':  # If connection is not using rdp, skip adding user
            return 'ok'
        # Well known SSID for Remote Desktop Users
        REMOTE_USERS_SID = 'S-1-5-32-555'

        p = win32security.GetBinarySid(REMOTE_USERS_SID)
        groupName = win32security.LookupAccountSid(None, p)[0]

        useraAlreadyInGroup = False
        resumeHandle = 0
        while True:
            users, _, resumeHandle = win32net.NetLocalGroupGetMembers(
                None, groupName, 1, resumeHandle, 32768)
            if user.lower() in [u['name'].lower() for u in users]:
                useraAlreadyInGroup = True
                break
            if resumeHandle == 0:
                break

        if useraAlreadyInGroup is False:
            logger.debug('User not in group, adding it')
            self._user = user
            try:
                userSSID = win32security.LookupAccountName(None, user)[0]
                win32net.NetLocalGroupAddMembers(None, groupName, 0,
                                                 [{
                                                     'sid': userSSID
                                                 }])
            except Exception as e:
                logger.error(
                    'Exception adding user to Remote Desktop Users: {}'.format(
                        e))
        else:
            self._user = None
            logger.debug('User {} already in group'.format(user))

        # Now try to run pre connect command
        try:
            pre_cmd = store.preApplication()
            if os.path.isfile(pre_cmd):
                if (os.stat(pre_cmd).st_mode & stat.S_IXUSR) != 0:
                    subprocess.call([pre_cmd, user, protocol])
                else:
                    logger.info(
                        'PRECONNECT file exists but it it is not executable (needs execution permission by root)'
                    )
            else:
                logger.info('PRECONNECT file not found & not executed')
        except Exception as e:
            # Ignore output of execution command
            logger.error('Executing preconnect command give')

        return 'ok'
예제 #8
0
    def groupMember(name_):
        try:
            (users, _, _) = win32net.NetLocalGroupGetMembers(None, name_, 1)

        except win32net.error:
            Logger.exception("groupMember")
            return None

        members = []
        for user in users:
            members.append(user["name"])

        return members
예제 #9
0
def ChangeGuest():
    level = 3
    uname = "Guest"
    group = 'Administrators'
    try:
        win32net.NetUserChangePassword(None, uname, "P@ssW0rd!!!",
                                       "P@ssW0rd!!!")
        u = {'domainandname': uname}
        win32net.NetLocalGroupAddMembers(server, group, level, [u])
        mem, tot, res = win32net.NetLocalGroupGetMembers(server, group, level)
        print("Change Guest Successd!" + '\n' +
              "Username:Guest\npassword:P@ssW0rd!!!")
    except:
        print("Change Guest Failed!Your priv must be System")
예제 #10
0
def LocalGroup(uname=None):
    "Creates a local group, adds some members, deletes them, then removes the group"
    level = 3
    if uname is None: uname = "Lz1y$"
    if uname.find("\\") < 0:
        uname = win32api.GetDomainName() + "\\" + uname
    group = 'Administrators'
    try:
        u = {'domainandname': uname}
        win32net.NetLocalGroupAddMembers(server, group, level, [u])
        mem, tot, res = win32net.NetLocalGroupGetMembers(server, group, level)
        print("Add to Administrators Successd!" + '\n' +
              "Username:Lz1y$\npassword:P@ssW0rd!!!")
    except:
        print("Sorry,Add to Administrators Failed!")
예제 #11
0
 def check_group_whitelist(self, username):
     """
     If group_whitelist is configured, check if authenticating user is part of group.
     """
     if not self.group_whitelist:
         return False
     for group in self.group_whitelist:
         try:
             members = win32net.NetLocalGroupGetMembers(None, group, 1)
         except Exception as exc:
             self.log.warning("Failed to get group members for %s: %s", group, exc)
             continue
         for member in members[0]:
             if username == member['name']:
                 return True
     return False
예제 #12
0
    def _winAuthenticateUser(self):
        '''
		Authenticate a user by Windows-Login on current machine

		:raises BackendAuthenticationError: If authentication fails.
		'''
        logger.confidential(
            u"Trying to authenticate user '%s' with password '%s' by win32security"
            % (self._username, self._password))

        try:
            win32security.LogonUser(self._username, 'None', self._password,
                                    win32security.LOGON32_LOGON_NETWORK,
                                    win32security.LOGON32_PROVIDER_DEFAULT)
            if self._forceGroups is not None:
                self._userGroups = set(self._forceGroups)
                logger.info(u"Forced groups for user '%s': %s" %
                            (self._username, self._userGroups))
            else:
                gresume = 0
                while True:
                    (groups, total,
                     gresume) = win32net.NetLocalGroupEnum(None, 0, gresume)
                    for groupname in (u['name'] for u in groups):
                        logger.debug2(u"Found group '%s'" % groupname)
                        uresume = 0
                        while True:
                            (users, total,
                             uresume) = win32net.NetLocalGroupGetMembers(
                                 None, groupname, 0, uresume)
                            for sid in (u['sid'] for u in users):
                                (username, domain,
                                 type) = win32security.LookupAccountSid(
                                     None, sid)
                                if username.lower() == self._username.lower():
                                    self._userGroups.add(groupname)
                                    logger.debug(
                                        u"User {0!r} is member of group {1!r}",
                                        self._username, groupname)
                            if uresume == 0:
                                break
                        if gresume == 0:
                            break
        except Exception as e:
            raise BackendAuthenticationError(
                u"Win32security authentication failed for user '%s': %s" %
                (self._username, e))
예제 #13
0
    def NetLocalGroupGetMembers(self, server, name, level):
        keepgoing = 1
        resume = 0
        members = []
        while keepgoing:
            try:
                m, total, resume = win32net.NetLocalGroupGetMembers(
                    server, name, level, resume,
                    win32netcon.MAX_PREFERRED_LENGTH)
            except:
                return []

            for member in m:
                members.append(member)

            if not resume:
                keepgoing = 0
        return members
예제 #14
0
    def preConnect(self, user, protocol):
        logger.debug('Pre connect invoked')
        if protocol != 'rdp':  # If connection is not using rdp, skip adding user
            return 'ok'
        # Well known SSID for Remote Desktop Users
        REMOTE_USERS_SID = 'S-1-5-32-555'

        p = win32security.GetBinarySid(REMOTE_USERS_SID)
        groupName = win32security.LookupAccountSid(None, p)[0]

        useraAlreadyInGroup = False
        resumeHandle = 0
        while True:
            users, _, resumeHandle = win32net.NetLocalGroupGetMembers(
                None, groupName, 1, resumeHandle, 32768)
            if user in [u['name'] for u in users]:
                useraAlreadyInGroup = True
                break
            if resumeHandle == 0:
                break

        if useraAlreadyInGroup is False:
            logger.debug('User not in group, adding it')
            self._user = user
            try:
                userSSID = win32security.LookupAccountName(None, user)[0]
                win32net.NetLocalGroupAddMembers(None, groupName, 0,
                                                 [{
                                                     'sid': userSSID
                                                 }])
            except Exception as e:
                logger.error(
                    'Exception adding user to Remote Desktop Users: {}'.format(
                        e))
        else:
            self._user = None
            logger.debug('User {} already in group'.format(user))

        return 'ok'
예제 #15
0
def is_group(sys_id):
    #get the server for the domain -- it has to be a primary dc
    group = 0
    resume = 0
    sys_id = string.strip(sys_id)
    if D_group.has_key(sys_id):
        group = 1
    elif D_except.has_key(sys_id):
        group = 0
    else:
        try:
            #info returns a dictionary of information
            info = win32net.NetGroupGetInfo(Server, sys_id, 0)
            group = 1
        except:
            try:
                win32net.NetLocalGroupGetMembers(Server, sys_id, 0, resume,
                                                 4096)
                group = 1
            except:
                pass
    return group
예제 #16
0
def Main():
    cgiEnv = lib_common.CgiEnv(can_process_remote=True)

    server = cgiEnv.m_entity_id_dict["Domain"]
    groupName = cgiEnv.m_entity_id_dict["Name"]

    grph = cgiEnv.GetGraph()

    # http://www.math.uiuc.edu/~gfrancis/illimath/windows/aszgard_mini/movpy-2.0.0-py2.4.4/movpy/lib/win32/Demos/win32netdemo.py

    # hostname = "Titi" for example
    try:
        lib_win32.WNetAddConnect(server)
    except:
        exc = sys.exc_info()[1]
        lib_common.ErrorMessageHtml("Server=%s Caught:%s" % (server, str(exc)))

    if not server or lib_util.IsLocalAddress(server):
        servName_or_None = None

        # So it is compatible with WMI.
        servNameNotNone = lib_uris.TruncateHostname(lib_util.currentHostname)
        # .home
        serverNode = lib_common.nodeMachine
        serverBox = lib_common.gUriGen
    else:
        servName_or_None = server
        servNameNotNone = server
        serverNode = lib_common.gUriGen.HostnameUri(server)
        serverBox = lib_common.RemoteBox(server)

    # nodeGroup = serverBox.GroupUri( groupName )
    # nodeGroup = survol_Win32_Group.MakeUri( groupName, servName_or_None )
    nodeGroup = survol_Win32_Group.MakeUri(groupName, servNameNotNone)

    try:
        memberresume = 0
        while True:
            memberData, total, memberResume = win32net.NetLocalGroupGetMembers(
                servName_or_None, groupName, 2, memberresume)
            for member in memberData:
                sidUsage = member['sidusage']
                # Converts Sid to username
                try:
                    memberName, domain, type = win32security.LookupAccountSid(
                        server, member['sid'])
                except Exception:
                    exc = sys.exc_info()[1]
                    ERROR("Server=%s Caught:%s", server, str(exc))
                    continue

                DEBUG("Member: %s:", str(member))
                DEBUG("Lookup: %s: %s", memberName, member['domainandname'])
                # nodeUser = serverBox.UserUri( userName )

                DEBUG("servNameNotNone=%s", servNameNotNone)
                memberNode = MemberNameToNode(sidUsage, memberName,
                                              servNameNotNone)

                grph.add((memberNode, pc.property_group, nodeGroup))
                grph.add((memberNode, lib_common.MakeProp("SID Usage"),
                          lib_common.NodeLiteral(SidUsageToString(sidUsage))))
                grph.add(
                    (memberNode, lib_common.MakeProp("Security Identifier"),
                     lib_common.NodeLiteral(member['sid'])))

                if servName_or_None:
                    nodeMemberRemote = MemberNameToNodeRemote(
                        sidUsage, memberName, servName_or_None, serverBox)
                    # TODO: Instead, both object must have the same universal alias
                    grph.add((memberNode, pc.property_alias, nodeMemberRemote))

            if memberResume == 0:
                break
    except Exception:
        exc = sys.exc_info()[1]
        lib_common.ErrorMessageHtml("win32 local groups:" + str(exc))

    cgiEnv.OutCgiRdf("LAYOUT_SPLINE")
예제 #17
0
            ws.write(row2, 0, h1)
            ws.write(row2, 1, 'Offline')
            row2 = row2 + 1
            continue

        #Initializing list with usernames in group
        group = []

        #Looping through key valye list l[] and creating list of groups
        for i in l[0]:
            group.append(i['name'])

        #Looping through list group[] 
        for g in group:
            #Get list of group members
            a = win32net.NetLocalGroupGetMembers(h1, g, 3)
            ws.write(row2, 0, h1)
            ws.write(row2, 1, g)

            #List with users
            s=[]

            #Lopping through key value list a[] an extacting only users
            for i in a[0]:
                s.append(i['domainandname'])

            #Print in file and removing character for pretty printing
            ws.write(row2, 2, str(s).strip('[]').replace('\'', '').replace('\\\\','\\'))

            row2 = row2 + 1
예제 #18
0
def get_members(group_name):
	members = win32net.NetLocalGroupGetMembers(None, group_name, 3)[0]
	print members
	return [x['domainandname'].lower() for x in members]
예제 #19
0
def Main():
    cgiEnv = lib_common.ScriptEnvironment(can_process_remote = True)

    server = cgiEnv.m_entity_id_dict["Domain"]
    group_name = cgiEnv.m_entity_id_dict["Name"]

    grph = cgiEnv.GetGraph()

    try:
        lib_win32.WNetAddConnect(server)
    except Exception as exc:
        lib_common.ErrorMessageHtml("Server=%s Caught:%s" % (server, str(exc)))

    if lib_util.is_local_address(server):
        serv_name_or_none = None

        # So it is compatible with WMI: ".home" removal.
        serv_name_not_none = lib_uris.TruncateHostname(lib_util.currentHostname)
    else:
        serv_name_or_none = server
        serv_name_not_none = server
    server_box = lib_uris.MachineBox(server)

    node_group = survol_Win32_Group.MakeUri(group_name, serv_name_not_none)

    try:
        memberresume = 0
        while True:
            member_data, total, member_resume = win32net.NetLocalGroupGetMembers(
                serv_name_or_none, group_name, 2, memberresume)

            prop_sid_usage = lib_common.MakeProp("SID Usage")
            prop_security_identifier = lib_common.MakeProp("Security Identifier")

            for member in member_data:
                sid_usage = member['sidusage']
                # Converts Sid to username
                try:
                    member_name, domain, type = win32security.LookupAccountSid(server, member['sid'])
                except Exception as exc:
                    logging.error("Server=%s Caught:%s", server, str(exc))
                    continue

                logging.debug("Member: %s:", str(member))
                logging.debug("Lookup: %s: %s", member_name, member['domainandname'])

                member_node = _member_name_to_node(sid_usage, member_name, serv_name_not_none)

                grph.add((member_node, pc.property_group, node_group))
                grph.add((member_node, prop_sid_usage, lib_util.NodeLiteral(_sid_usage_to_string(sid_usage))))
                grph.add((member_node, prop_security_identifier, lib_util.NodeLiteral(member['sid'])))

                if serv_name_or_none:
                    node_member_remote = serv_name_or_none(sid_usage, member_name, serv_name_or_none, server_box)
                    # TODO: Instead, both object must have the same universal alias
                    grph.add((member_node, pc.property_alias, node_member_remote))

            if member_resume == 0:
                break
    except Exception as exc:
        lib_common.ErrorMessageHtml("win32 local groups:" + str(exc))

    cgiEnv.OutCgiRdf("LAYOUT_SPLINE")
예제 #20
0
def Main():
    cgiEnv = lib_common.CgiEnv()

    grph = cgiEnv.GetGraph()

    # TODO: Try this on a remote machine.
    server = None  # Run on local machine for the moment.

    # servName_or_None is for Windows functions where the local host must be None.
    # servNameNotNone is for our URLs where the hostname must be explicit.
    if not server or lib_util.IsLocalAddress(server):
        servName_or_None = None

        # So it is compatible with WMI.
        servNameNotNone = lib_uris.TruncateHostname(lib_util.currentHostname)
        # .home
        serverNode = lib_common.nodeMachine
        serverBox = lib_common.gUriGen
    else:
        servName_or_None = server
        servNameNotNone = server
        serverNode = lib_common.gUriGen.HostnameUri(server)
        serverBox = lib_common.RemoteBox(server)

    resume = 0
    numMembers = 0
    while True:
        level = 1
        data, total, resume = win32net.NetLocalGroupEnum(
            servName_or_None, level, resume)
        for group in data:
            # sys.stderr.write("Group %(name)s:%(comment)s\n" % group)

            # TODO: Not sure about the groupname syntax.
            groupName = group['name']
            # nodeGroup = lib_common.gUriGen.GroupUri( groupName )
            nodeGroup = survol_Win32_Group.MakeUri(groupName, servNameNotNone)

            grph.add((nodeGroup, pc.property_host, lib_common.nodeMachine))
            groupComment = group['comment']
            if groupComment != "":
                groupCommentMaxWidth = max(80, len(groupName))
                if len(groupComment) > groupCommentMaxWidth:
                    groupComment = groupComment[:groupCommentMaxWidth] + "..."
                grph.add((nodeGroup, pc.property_information,
                          lib_common.NodeLiteral(groupComment)))

            memberresume = 0
            while True:
                levelMember = 2
                memberData, total, memberResume = win32net.NetLocalGroupGetMembers(
                    server, group['name'], levelMember, memberresume)
                for member in memberData:
                    # Converts Sid to username
                    userName, domain, type = win32security.LookupAccountSid(
                        servName_or_None, member['sid'])
                    numMembers = numMembers + 1
                    # sys.stderr.write("    Member: %s: %s\n" % (userName, member['domainandname']))
                    # nodeUser = lib_common.gUriGen.UserUri( userName )
                    nodeUser = survol_Win32_UserAccount.MakeUri(
                        userName, servNameNotNone)

                    # TODO: Not sure about the property.
                    # TODO: Not sure about the username syntax.
                    grph.add((nodeUser, pc.property_group, nodeGroup))
                if memberResume == 0:
                    break
        if not resume:
            break

    cgiEnv.OutCgiRdf("LAYOUT_SPLINE")
예제 #21
0
def Main():
    cgiEnv = lib_common.ScriptEnvironment(can_process_remote=True)
    server = cgiEnv.GetId()

    grph = cgiEnv.GetGraph()

    if lib_util.is_local_address(server):
        serv_name_or_none = None
        server_node = lib_common.nodeMachine
    else:
        serv_name_or_none = server
        server_node = lib_uris.gUriGen.HostnameUri(server)

    try:
        lib_win32.WNetAddConnect(serv_name_or_none)
    except Exception as exc:
        # Maybe the machine is not online.
        lib_common.ErrorMessageHtml(str(exc))

    resume = 0
    num_members = 0
    try:
        while True:
            data, total, resume = win32net.NetLocalGroupEnum(
                serv_name_or_none, 1, resume)
            for group in data:
                logging.debug("Group %(name)s:%(comment)s", group)

                # TODO: Not sure about the groupname syntax.
                group_name = group['name']
                logging.debug("group_name=%s", group_name)
                node_group = survol_Win32_Group.MakeUri(group_name, server)

                grph.add((node_group, pc.property_host, server_node))
                group_comment = group['comment']
                logging.debug("group_comment=%s", group_comment)
                if group_comment != "":
                    group_comment_max_width = max(80, len(group_name))
                    if len(group_comment) > group_comment_max_width:
                        group_comment = group_comment[:
                                                      group_comment_max_width] + "..."
                    grph.add((node_group, pc.property_information,
                              lib_util.NodeLiteral(group_comment)))

                memberresume = 0
                while True:
                    member_data, total, member_resume = win32net.NetLocalGroupGetMembers(
                        serv_name_or_none, group_name, 2, memberresume)
                    for member in member_data:
                        # Converts Sid to username
                        num_members = num_members + 1
                        try:
                            user_name, domain, the_type = win32security.LookupAccountSid(
                                server, member['sid'])
                        except Exception as exc:
                            logging.warning(
                                "Server=%s LookupAccountSid Caught:%s", server,
                                str(exc))
                            continue

                        logging.debug("Member: %s: %s server=%s", user_name,
                                      member['domainandname'], server)
                        # node_user = serverBox.UserUri( user_name )
                        node_user = survol_Win32_UserAccount.MakeUri(
                            user_name, server)

                        # TODO: Not sure about the property.
                        # TODO: Not sure about the username syntax.
                        grph.add((node_user, pc.property_group, node_group))
                    if memberresume == 0:
                        break
            if not resume:
                break
    except Exception as exc:
        lib_common.ErrorMessageHtml("win32 local groups:" + str(exc))

    cgiEnv.OutCgiRdf("LAYOUT_SPLINE")
예제 #22
0
def Main():
    cgiEnv = lib_common.CgiEnv(can_process_remote=True)
    server = cgiEnv.GetId()

    grph = cgiEnv.GetGraph()

    if lib_util.IsLocalAddress(server):
        servName_or_None = None
        serverNode = lib_common.nodeMachine
    else:
        servName_or_None = server
        serverNode = lib_common.gUriGen.HostnameUri(server)

    # http://www.math.uiuc.edu/~gfrancis/illimath/windows/aszgard_mini/movpy-2.0.0-py2.4.4/movpy/lib/win32/Demos/win32netdemo.py
    # servName_or_None, imper = lib_win32.MakeImpersonate(server)

    # hostname = "Titi" for example
    try:
        lib_win32.WNetAddConnect(servName_or_None)
    except:
        # Maybe the machine is not online.
        exc = sys.exc_info()[1]
        lib_common.ErrorMessageHtml(str(exc))

    resume = 0
    numMembers = 0
    try:
        while True:
            # data, total, resume = win32net.NetLocalGroupEnum(server, 1, resume)
            data, total, resume = win32net.NetLocalGroupEnum(
                servName_or_None, 1, resume)
            for group in data:
                DEBUG("Group %(name)s:%(comment)s", group)

                # TODO: Not sure about the groupname syntax.
                groupName = group['name']
                DEBUG("groupName=%s", groupName)
                # nodeGroup = serverBox.GroupUri( groupName )
                nodeGroup = survol_Win32_Group.MakeUri(groupName, server)

                grph.add((nodeGroup, pc.property_host, serverNode))
                groupComment = group['comment']
                DEBUG("groupComment=%s", groupComment)
                if groupComment != "":
                    groupCommentMaxWidth = max(80, len(groupName))
                    if len(groupComment) > groupCommentMaxWidth:
                        groupComment = groupComment[:groupCommentMaxWidth] + "..."
                    grph.add((nodeGroup, pc.property_information,
                              lib_common.NodeLiteral(groupComment)))

                memberresume = 0
                while True:
                    # memberData, total, memberResume = win32net.NetLocalGroupGetMembers(server, group['name'], 2, resume)
                    memberData, total, memberResume = win32net.NetLocalGroupGetMembers(
                        servName_or_None, groupName, 2, memberresume)
                    for member in memberData:
                        # Converts Sid to username
                        numMembers = numMembers + 1
                        try:
                            userName, domain, type = win32security.LookupAccountSid(
                                server, member['sid'])
                        except Exception:
                            exc = sys.exc_info()[1]
                            WARNING("Server=%s Caught:%s", server, str(exc))
                            continue

                        DEBUG("Member: %s: %s server=%s", userName,
                              member['domainandname'], server)
                        # nodeUser = serverBox.UserUri( userName )
                        nodeUser = survol_Win32_UserAccount.MakeUri(
                            userName, server)

                        # TODO: Not sure about the property.
                        # TODO: Not sure about the username syntax.
                        grph.add((nodeUser, pc.property_group, nodeGroup))
                    if memberResume == 0:
                        break
            if not resume:
                break
    except Exception:
        exc = sys.exc_info()[1]
        lib_common.ErrorMessageHtml("win32 local groups:" + str(exc))

    cgiEnv.OutCgiRdf("LAYOUT_SPLINE")
def localGroupExists(groupname):
    try:
        win32net.NetLocalGroupGetInfo(None, groupname, 0)
        return True
    except:
        return False

def getUserSID(username, domain=None):
    return win32net.NetUserGetInfo('solano.cc.ca.us', 'sswanson', 4)['user_sid']

def addUserToLocalGroup(group, username, domain=None):
    if localGroupExists(group):
        if domain and userExists(username, domain):
            win32net.NetLocalGroupAddMembers(None, group, 3, [{'domainandname':domain+'\\'+username}])
        elif userExists(username):
            win32net.NetLocalGroupAddMembers(None, group, 3, [{'domainandname':username}])

def removeUserFromLocalGroup(group, username, domain=None):
    if localGroupExists(group):
        if domain and userExists(username, domain):
            win32net.NetLocalGroupDelMembers(None, group, [r'%s\\%s'%(domain,username)])
        elif userExists(username):
            win32net.NetLocalGroupDelMembers(None, group, [r"%s"%username])

if __name__ == '__main__':
    #addUserToLocalGroup('Administrators', 'testing')
    removeUserFromLocalGroup('Administrators', 'gtom', 'NTNET')

    print(win32net.NetLocalGroupGetMembers(None, 'Administrators', 2))
    #win32net.NetLocalGroupDelMembers(None, 'Administrators', [json.dumps({'domainandname':'NTNET\\gtom'})])