Hello community,

here is the log from the commit of package yast2-adcommon-python for 
openSUSE:Factory checked in at 2019-06-18 14:59:25
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/yast2-adcommon-python (Old)
 and      /work/SRC/openSUSE:Factory/.yast2-adcommon-python.new.4811 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "yast2-adcommon-python"

Tue Jun 18 14:59:25 2019 rev:5 rq:710511 version:0.7

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/yast2-adcommon-python/yast2-adcommon-python.changes  
    2019-05-16 22:08:37.118360133 +0200
+++ 
/work/SRC/openSUSE:Factory/.yast2-adcommon-python.new.4811/yast2-adcommon-python.changes
    2019-06-18 14:59:26.669295119 +0200
@@ -1,0 +2,15 @@
+Mon Jun 17 19:23:59 UTC 2019 - [email protected]
+
+- Pass the domain name to the samba Credentials object; (bsc#1138487);
+- YaST aduc/adsi/gpmc should not exit after entering empty password.
+  Also, explicitly state that an Active Directory administrator should
+  sign in; (bsc#1132565);
+- 0.7
+
+-------------------------------------------------------------------
+Thu Jun 13 19:33:00 UTC 2019 - [email protected]
+
+- Move schema parsing code from adsi to the common code; (bsc#1138203);
+- 0.6
+
+-------------------------------------------------------------------

Old:
----
  yast2-adcommon-python-0.5.tar.bz2

New:
----
  yast2-adcommon-python-0.7.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ yast2-adcommon-python.spec ++++++
--- /var/tmp/diff_new_pack.Bnnxbe/_old  2019-06-18 14:59:27.177294867 +0200
+++ /var/tmp/diff_new_pack.Bnnxbe/_new  2019-06-18 14:59:27.181294865 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           yast2-adcommon-python
-Version:        0.5
+Version:        0.7
 Release:        0
 Summary:        Common code for the yast python ad modules
 License:        GPL-3.0-or-later

++++++ yast2-adcommon-python-0.5.tar.bz2 -> yast2-adcommon-python-0.7.tar.bz2 
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-adcommon-python-0.5/adcommon/creds.py 
new/yast2-adcommon-python-0.7/adcommon/creds.py
--- old/yast2-adcommon-python-0.5/adcommon/creds.py     2019-05-15 
16:56:47.000000000 +0200
+++ new/yast2-adcommon-python-0.7/adcommon/creds.py     2019-06-18 
11:11:12.000000000 +0200
@@ -173,8 +173,6 @@
                     if self.possible_save_creds:
                         save = UI.QueryWidget('remember_prompt', 'Value')
                     UI.CloseDialog()
-                    if not password:
-                        return False
                     if self.possible_save_creds:
                         if save:
                             self.__set_keyring(user, dom, password)
@@ -182,10 +180,13 @@
                             self.__delete_keyring()
                     self.creds.set_username(user)
                     self.creds.set_password(password)
+                    if dom:
+                        self.creds.set_domain(dom)
                     return True
                 if str(subret) == 'krb_select':
                     user = UI.QueryWidget('krb_select', 'Label')[1:]
                     self.creds.set_username(user)
+                    self.creds.set_domain(UI.QueryWidget('krb_realm', 'Value'))
                     self.__validate_kinit()
                     if self.creds.get_kerberos_state() == MUST_USE_KERBEROS:
                         UI.CloseDialog()
@@ -278,13 +279,16 @@
                     krb_selection = Frame('', VBox(
                         VSpacing(.5),
                         Left(PushButton(Id('krb_select'), Opt('hstretch', 
'vstretch'), krb_user)),
-                        Left(Label(b'Domain: %s' % krb_realm))
+                        HBox(
+                            HWeight(1, Left(Label('Domain:'))),
+                            HWeight(4, Left(Label(Id('krb_realm'), 
Opt('hstretch'), krb_realm))),
+                        ),
                     ))
                 elif krb_user and krb_expired:
                     user = krb_user
         return MinWidth(30, HBox(HSpacing(1), VBox(
             VSpacing(.5),
-            Left(Label('To continue, type an administrator password')),
+            Left(Label('To continue, type an Active Directory administrator 
password')),
             Frame('', VBox(
                 Left(TextEntry(Id('username_prompt'), Opt('hstretch', 
'notify'), 'Username', user)),
                 Left(Password(Id('password_prompt'), Opt('hstretch'), 
'Password', password)),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-adcommon-python-0.5/adcommon/yldap.py 
new/yast2-adcommon-python-0.7/adcommon/yldap.py
--- old/yast2-adcommon-python-0.5/adcommon/yldap.py     2019-05-15 
16:56:47.000000000 +0200
+++ new/yast2-adcommon-python-0.7/adcommon/yldap.py     2019-06-18 
11:11:12.000000000 +0200
@@ -12,6 +12,8 @@
 import os
 import six
 import ldapurl
+import binascii, struct, re
+from datetime import datetime
 
 def y2error_dialog(msg):
     from yast import UI, Opt, HBox, HSpacing, VBox, VSpacing, Label, Right, 
PushButton, Id
@@ -70,8 +72,11 @@
         self.lp = lp
         self.creds = creds
         self.realm = lp.get('realm')
+        self.realm_dn = ','.join(['DC=%s' % part for part in 
self.realm.lower().split('.')])
         self.ldap_url = ldapurl.LDAPUrl(ldap_url) if ldap_url else None
         self.__ldap_connect()
+        self.schema = {}
+        self.__load_schema()
 
     def __ldap_exc_msg(self, e):
         if len(e.args) > 0 and \
@@ -175,3 +180,129 @@
             ycpbuiltins.y2error(traceback.format_exc())
             ycpbuiltins.y2error('ldap.delete_s: %s\n' % self.__ldap_exc_msg(e))
 
+    def __find_inferior_classes(self, name):
+        dn = 'CN=Schema,CN=Configuration,%s' % self.realm_dn
+        search = '(|(possSuperiors=%s)(systemPossSuperiors=%s))' % (name, name)
+        return [item[-1]['lDAPDisplayName'][-1] for item in 
self.ldap_search_s(dn, SCOPE_SUBTREE, search, ['lDAPDisplayName'])]
+
+    def __load_schema(self):
+        dn = self.l.search_subschemasubentry_s()
+        results = self.l.read_subschemasubentry_s(dn)
+
+        self.schema['attributeTypes'] = {}
+        self.schema['constructedAttributes'] = self.__constructed_attributes()
+        for attributeType in results['attributeTypes']:
+            m = 
re.match(b'\(\s+(?P<id>[0-9\.]+)\s+NAME\s+\'(?P<name>[\-\w]+)\'\s+(SYNTAX\s+\'(?P<syntax>[0-9\.]+)\'\s+)?(?P<info>.*)\)',
 attributeType)
+            if m:
+                name = m.group('name')
+                self.schema['attributeTypes'][name] = {}
+                self.schema['attributeTypes'][name]['id'] = m.group('id')
+                self.schema['attributeTypes'][name]['syntax'] = 
m.group('syntax')
+                self.schema['attributeTypes'][name]['multi-valued'] = 
b'SINGLE-VALUE' not in m.group('info')
+                self.schema['attributeTypes'][name]['collective'] = 
b'COLLECTIVE' in m.group('info')
+                self.schema['attributeTypes'][name]['user-modifiable'] = 
b'NO-USER-MODIFICATION' not in m.group('info')
+                if b'USAGE' in m.group('info'):
+                    usage = re.findall(b'.*\s+USAGE\s+(\w+)', m.group('info'))
+                    self.schema['attributeTypes'][name]['usage'] = usage[-1] 
if usage else b'userApplications'
+                else:
+                    self.schema['attributeTypes'][name]['usage'] = 
b'userApplications'
+            else:
+                raise ldap.LDAPError('Failed to parse attributeType: %s' % 
attributeType.decode())
+
+        self.schema['objectClasses'] = {}
+        for objectClass in results['objectClasses']:
+            m = 
re.match(b'\(\s+(?P<id>[0-9\.]+)\s+NAME\s+\'(?P<name>[\-\w]+)\'\s+(SUP\s+(?P<superior>[\-\w]+)\s+)?(?P<type>\w+)\s+(MUST\s+\((?P<must>[^\)]*)\)\s+)?(MAY\s+\((?P<may>[^\)]*)\)\s+)?\)',
 objectClass)
+            if m:
+                name = m.group('name')
+                self.schema['objectClasses'][name] = {}
+                self.schema['objectClasses'][name]['id'] = m.group('id')
+                self.schema['objectClasses'][name]['superior'] = 
m.group('superior')
+                self.schema['objectClasses'][name]['inferior'] = 
self.__find_inferior_classes(name.decode())
+                self.schema['objectClasses'][name]['type'] = m.group('type')
+                self.schema['objectClasses'][name]['must'] = 
m.group('must').strip().split(b' $ ') if m.group('must') else []
+                self.schema['objectClasses'][name]['may'] = 
m.group('may').strip().split(b' $ ') if m.group('may') else []
+            else:
+                raise ldap.LDAPError('Failed to parse objectClass: %s' % 
objectClass.decode())
+
+        self.schema['dITContentRules'] = {}
+        for dITContentRule in results['dITContentRules']:
+            m = 
re.match(b'\(\s+(?P<id>[0-9\.]+)\s+NAME\s+\'(?P<name>[\-\w]+)\'\s*(AUX\s+\((?P<aux>[^\)]*)\))?\s*(MUST\s+\((?P<must>[^\)]*)\)\s+)?\s*(MAY\s+\((?P<may>[^\)]*)\))?\s*(NOT\s+\((?P<not>[^\)]*)\))?\s*\)',
 dITContentRule)
+            if m:
+                name = m.group('name')
+                self.schema['dITContentRules'][name] = {}
+                self.schema['dITContentRules'][name]['id'] = m.group('id')
+                self.schema['dITContentRules'][name]['must'] = 
m.group('must').strip().split(b' $ ') if m.group('must') else []
+                self.schema['dITContentRules'][name]['may'] = 
m.group('may').strip().split(b' $ ') if m.group('may') else []
+                self.schema['dITContentRules'][name]['aux'] = 
m.group('aux').strip().split(b' $ ') if m.group('aux') else []
+                self.schema['dITContentRules'][name]['not'] = 
m.group('not').strip().split(b' $ ') if m.group('not') else []
+            else:
+                raise ldap.LDAPError('Failed to parse dITContentRule: %s' % 
dITContentRule.decode())
+
+    def __constructed_attributes(self):
+        # ADSI Hides constructed attributes, since they can't be modified.
+        # 1.2.840.113556.1.4.803 is the OID for LDAP_MATCHING_RULE_BIT_AND 
(we're and'ing 4 on systemFlags)
+        search = 
'(&(systemFlags:1.2.840.113556.1.4.803:=4)(ObjectClass=attributeSchema))'
+        container = 'CN=Schema,CN=Configuration,%s' % self.realm_dn
+        ret = self.ldap_search(container, SCOPE_ONELEVEL, search, 
['lDAPDisplayName'])
+        return [a[-1]['lDAPDisplayName'][-1] for a in ret]
+
+    def __timestamp(self, val):
+        return str(datetime.strptime(val.decode(), '%Y%m%d%H%M%S.%fZ'))
+
+    def __display_value_each(self, syntax, key, val):
+        # rfc4517 Generalized Time syntax
+        if syntax == b'1.3.6.1.4.1.1466.115.121.1.24':
+            return self.__timestamp(val)
+        # rfc4517 Octet String syntax
+        if syntax == b'1.3.6.1.4.1.1466.115.121.1.40':
+            if key == 'objectGUID':
+                return octet_string_to_objectGUID(val)
+            elif key == 'objectSid':
+                return octet_string_to_objectSid(val)
+            else:
+                return octet_string_to_hex(val)
+        return val
+
+    def display_schema_value(self, key, val):
+        if key.encode() in self.schema['attributeTypes']:
+            attr_type = self.schema['attributeTypes'][key.encode()]
+        else:
+            # RootDSE attributes don't show up in the schema, so we have to 
guess
+            if len(val) > 1: # multi-valued
+                return '; '.join([v.decode() for v in val])
+            return val[-1]
+        if val == None:
+            return '<not set>'
+        else:
+            if not attr_type['multi-valued']:
+                return self.__display_value_each(attr_type['syntax'], key, 
val[-1])
+            ret = []
+            for sval in val:
+                nval = self.__display_value_each(attr_type['syntax'], key, 
sval)
+                if isinstance(nval, six.binary_type):
+                    nval = nval.decode()
+                ret.append(nval)
+            return '; '.join(ret)
+
+def octet_string_to_hex(data):
+    return binascii.hexlify(data)
+
+def octet_string_to_objectGUID(data):
+    return '%s-%s-%s-%s-%s' % ('%02x' % struct.unpack('<L', data[0:4])[0],
+                               '%02x' % struct.unpack('<H', data[4:6])[0],
+                               '%02x' % struct.unpack('<H', data[6:8])[0],
+                               '%02x' % struct.unpack('>H', data[8:10])[0],
+                               '%02x%02x' % struct.unpack('>HL', data[10:]))
+
+def octet_string_to_objectSid(data):
+    if struct.unpack('B', chr(data[0]).encode())[0] == 1:
+        length = struct.unpack('B', chr(data[1]).encode())[0]-1
+        security_nt_authority = struct.unpack('>xxL', data[2:8])[0]
+        security_nt_non_unique = struct.unpack('<L', data[8:12])[0]
+        ret = 'S-1-%d-%d' % (security_nt_authority, security_nt_non_unique)
+        for i in range(length):
+            pos = 12+(i*4)
+            ret += '-%d' % struct.unpack('<L', data[pos:pos+4])
+        return ret
+    else:
+        return octet_string_to_hex(data)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-adcommon-python-0.5/package/yast2-adcommon-python.changes 
new/yast2-adcommon-python-0.7/package/yast2-adcommon-python.changes
--- old/yast2-adcommon-python-0.5/package/yast2-adcommon-python.changes 
2019-05-15 16:56:47.000000000 +0200
+++ new/yast2-adcommon-python-0.7/package/yast2-adcommon-python.changes 
2019-06-18 11:11:12.000000000 +0200
@@ -1,4 +1,19 @@
 -------------------------------------------------------------------
+Mon Jun 17 19:23:59 UTC 2019 - [email protected]
+
+- Pass the domain name to the samba Credentials object; (bsc#1138487);
+- YaST aduc/adsi/gpmc should not exit after entering empty password.
+  Also, explicitly state that an Active Directory administrator should
+  sign in; (bsc#1132565);
+- 0.7
+
+-------------------------------------------------------------------
+Thu Jun 13 19:33:00 UTC 2019 - [email protected]
+
+- Move schema parsing code from adsi to the common code; (bsc#1138203);
+- 0.6
+
+-------------------------------------------------------------------
 Wed May 15 14:49:21 UTC 2019 - [email protected]
 
 - "TypeError: Expected a string or unicode object" during auth;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-adcommon-python-0.5/package/yast2-adcommon-python.spec 
new/yast2-adcommon-python-0.7/package/yast2-adcommon-python.spec
--- old/yast2-adcommon-python-0.5/package/yast2-adcommon-python.spec    
2019-05-15 16:56:47.000000000 +0200
+++ new/yast2-adcommon-python-0.7/package/yast2-adcommon-python.spec    
2019-06-18 11:11:12.000000000 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           yast2-adcommon-python
-Version:        0.5
+Version:        0.7
 Release:        0
 Summary:        Common code for the yast python ad modules
 License:        GPL-3.0+


Reply via email to