Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
init fix of get_users() - non admin users now found rockstor#2564
Browse files Browse the repository at this point in the history
Move to more modern - time limited subprocess.run().
phillxnet committed Jun 5, 2023
1 parent d655796 commit 1eee2ca
Showing 2 changed files with 29 additions and 44 deletions.
2 changes: 1 addition & 1 deletion src/rockstor/storageadmin/views/ug_helpers.py
Original file line number Diff line number Diff line change
@@ -34,7 +34,7 @@ def combined_users():
uo.uid = sys_users[u][0]
uo.gid = sys_users[u][1]
uo.shell = sys_users[u][2]
gname = get_groups(uo.gid).keys()[0]
gname = list(get_groups(uo.gid).keys())[0]
create = True
if uo.group is not None:
if uo.group.gid == uo.gid or uo.group.groupname == gname:
71 changes: 28 additions & 43 deletions src/rockstor/system/users.py
Original file line number Diff line number Diff line change
@@ -16,21 +16,16 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import crypt
import fcntl
import grp
import logging
import os
import pwd
import random
import re
import stat
import string
import subprocess
import time
from subprocess import run, Popen, PIPE
from shutil import move
from tempfile import mkstemp

from charset_normalizer import from_bytes
import dbus
from dbus import DBusException

@@ -62,46 +57,36 @@
}


# this is a hack for AD to get as many users as possible within 90 seconds. If
# this is a hack for AD to get as many users as possible within 60 seconds. If
# there are several thousands of domain users and AD isn't that fast, winbind
# takes a long time to enumerate the users for getent. Subsequent queries
# finish faster because of caching. But this prevents timing out.
def get_users(max_wait=90):
t0 = time.time()
def get_users(max_wait=60):
users = {}
p = subprocess.Popen(
# TODO: In Python 3.7 we have a capture_output option.
result = run(
["/usr/bin/getent", "passwd"],
shell=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdout=PIPE,
stderr=PIPE,
encoding="utf-8",
# stdout and stderr as string
universal_newlines=True, # 3.7 adds text parameter universal_newlines alias
timeout=max_wait,
)
fcntl.fcntl(p.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
alive = True
user_data = ""
while alive:
try:
if p.poll() is not None:
alive = False
user_data += p.stdout.read()
except IOError:
if time.time() - t0 < max_wait:
continue
except Exception as e:
logger.exception(e)
p.terminate()
uf = user_data.split("\n")
# If the feed ends in \n, the last element will be '', if not, it will
# be a partial line to be processed next time around.
user_data = uf[-1]
for u in uf[:-1]:
ufields = u.split(":")
if len(ufields) > 3:
charset = from_bytes(ufields[0]).best()
uname = ufields[0].decode(charset)
users[uname] = (int(ufields[2]), int(ufields[3]), str(ufields[6]))
if time.time() - t0 > max_wait:
p.terminate()
break
out = result.stdout
err = result.stderr
rc = result.returncode
# TODO: Report & handle exception reported via CompletedProcess (result)
out_list = out.split("\n")
# out_list looks like;
# ['root:x:0:0:root:/root:/bin/bash', ...
# 'radmin:x:1000:100::/home/radmin:/bin/bash', '']
for line in out_list[:-1]: # skip empty last line.
fields = line.split(":")
if len(fields) > 3:
uname = fields[0]
users[uname] = (int(fields[2]), int(fields[3]), str(fields[6]))
return users


@@ -207,12 +192,12 @@ def usermod(username, passwd):

def smbpasswd(username, passwd):
cmd = [SMBPASSWD, "-s", "-a", username]
p = subprocess.Popen(
p = Popen(
cmd,
shell=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE,
stdout=PIPE,
stderr=PIPE,
stdin=PIPE,
)
pstr = "%s\n%s\n" % (passwd, passwd)
out, err = p.communicate(input=pstr.encode("utf8"))

0 comments on commit 1eee2ca

Please sign in to comment.