mds/app-admin/mmc-core/files/mmc-core-3.0.0-kerberos-1.p...

402 lines
17 KiB
Diff

Submitted By: Mario Fetka (geos_one) (mario dot fetka at gmail dot com)
Date: 2010-05-01
Initial Package Version: 2.3.1
Origin: http://mds.mandriva.org/ticket/144
Upstream Status: unknown
Description: add support for kerberos attributes
diff -Naur mmc-core-3.0.0.orig/agent/conf/plugins/kerberos.ini mmc-core-3.0.0/agent/conf/plugins/kerberos.ini
--- mmc-core-3.0.0.orig/agent/conf/plugins/kerberos.ini 1970-01-01 00:00:00.000000000 +0000
+++ mmc-core-3.0.0/agent/conf/plugins/kerberos.ini 2010-05-01 12:06:44.124872375 +0000
@@ -0,0 +1,5 @@
+[main]
+disable = 0
+
+[kerberos]
+realm = EXAMPLE.COM
diff -Naur mmc-core-3.0.0.orig/agent/contrib/ldap/krb5-kdc.schema mmc-core-3.0.0/agent/contrib/ldap/krb5-kdc.schema
--- mmc-core-3.0.0.orig/agent/contrib/ldap/krb5-kdc.schema 1970-01-01 00:00:00.000000000 +0000
+++ mmc-core-3.0.0/agent/contrib/ldap/krb5-kdc.schema 2010-05-01 12:06:44.135874159 +0000
@@ -0,0 +1,136 @@
+# $Id: krb5-kdc.schema,v 1.1 2004-03-22 17:25:05 quanah Exp $
+# Definitions for a Kerberos V KDC schema
+
+# OID Base is iso(1) org(3) dod(6) internet(1) private(4) enterprise(1) padl(5322) kdcSchema(10)
+#
+# Syntaxes are under 1.3.6.1.4.1.5322.10.0
+# Attributes types are under 1.3.6.1.4.1.5322.10.1
+# Object classes are under 1.3.6.1.4.1.5322.10.2
+
+# Syntax definitions
+
+#krb5KDCFlagsSyntax SYNTAX ::= {
+# WITH SYNTAX INTEGER
+#-- initial(0), -- require as-req
+#-- forwardable(1), -- may issue forwardable
+#-- proxiable(2), -- may issue proxiable
+#-- renewable(3), -- may issue renewable
+#-- postdate(4), -- may issue postdatable
+#-- server(5), -- may be server
+#-- client(6), -- may be client
+#-- invalid(7), -- entry is invalid
+#-- require-preauth(8), -- must use preauth
+#-- change-pw(9), -- change password service
+#-- require-hwauth(10), -- must use hwauth
+#-- ok-as-delegate(11), -- as in TicketFlags
+#-- user-to-user(12), -- may use user-to-user auth
+#-- immutable(13) -- may not be deleted
+# ID { 1.3.6.1.4.1.5322.10.0.1 }
+#}
+
+#krb5PrincipalNameSyntax SYNTAX ::= {
+# WITH SYNTAX OCTET STRING
+#-- String representations of distinguished names as per RFC1510
+# ID { 1.3.6.1.4.1.5322.10.0.2 }
+#}
+
+# Attribute type definitions
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.1
+ NAME 'krb5PrincipalName'
+ DESC 'The unparsed Kerberos principal name'
+ EQUALITY caseExactIA5Match
+ SINGLE-VALUE
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.2
+ NAME 'krb5KeyVersionNumber'
+ EQUALITY integerMatch
+ SINGLE-VALUE
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.3
+ NAME 'krb5MaxLife'
+ EQUALITY integerMatch
+ SINGLE-VALUE
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.4
+ NAME 'krb5MaxRenew'
+ EQUALITY integerMatch
+ SINGLE-VALUE
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.5
+ NAME 'krb5KDCFlags'
+ EQUALITY integerMatch
+ SINGLE-VALUE
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.6
+ NAME 'krb5EncryptionType'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.7
+ NAME 'krb5ValidStart'
+ EQUALITY generalizedTimeMatch
+ ORDERING generalizedTimeOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+ SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.8
+ NAME 'krb5ValidEnd'
+ EQUALITY generalizedTimeMatch
+ ORDERING generalizedTimeOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+ SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.9
+ NAME 'krb5PasswordEnd'
+ EQUALITY generalizedTimeMatch
+ ORDERING generalizedTimeOrderingMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+ SINGLE-VALUE )
+
+# this is temporary; keys will eventually
+# be child entries or compound attributes.
+attributetype ( 1.3.6.1.4.1.5322.10.1.10
+ NAME 'krb5Key'
+ DESC 'Encoded ASN1 Key as an octet string'
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.11
+ NAME 'krb5PrincipalRealm'
+ DESC 'Distinguished name of krb5Realm entry'
+ SUP distinguishedName )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.12
+ NAME 'krb5RealmName'
+ EQUALITY octetStringMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )
+
+# Object class definitions
+
+objectclass ( 1.3.6.1.4.1.5322.10.2.1
+ NAME 'krb5Principal'
+ SUP top
+ AUXILIARY
+ MUST ( krb5PrincipalName )
+ MAY ( cn $ krb5PrincipalRealm ) )
+
+objectclass ( 1.3.6.1.4.1.5322.10.2.2
+ NAME 'krb5KDCEntry'
+ SUP krb5Principal
+ AUXILIARY
+ MUST ( krb5KeyVersionNumber )
+ MAY ( krb5ValidStart $ krb5ValidEnd $ krb5PasswordEnd $
+ krb5MaxLife $ krb5MaxRenew $ krb5KDCFlags $
+ krb5EncryptionType $ krb5Key ) )
+
+objectclass ( 1.3.6.1.4.1.5322.10.2.3
+ NAME 'krb5Realm'
+ SUP top
+ AUXILIARY
+ MUST ( krb5RealmName ) )
+
diff -Naur mmc-core-3.0.0.orig/agent/mmc/plugins/base/__init__.py mmc-core-3.0.0/agent/mmc/plugins/base/__init__.py
--- mmc-core-3.0.0.orig/agent/mmc/plugins/base/__init__.py 2010-05-01 12:06:18.101620060 +0000
+++ mmc-core-3.0.0/agent/mmc/plugins/base/__init__.py 2010-05-01 12:06:44.129620791 +0000
@@ -1286,6 +1286,10 @@
attrs = []
attrib = self.l.search_s(dn, ldap.SCOPE_BASE)
c, attrs = attrib[0]
+ # kerberos -> remove binary key from attrs
+ try: attrs.pop('krb5Key')
+ except: pass
+ #
newattrs = copy.deepcopy(attrs)
return newattrs
@@ -1315,6 +1319,10 @@
attrib = self.l.search_s(cn, ldap.SCOPE_BASE, attrlist = myattrlist)
c,attrs=attrib[0]
+ # kerberos -> remove binary key from attrs
+ try: attrs.pop('krb5Key')
+ except: pass
+ #
newattrs = copy.deepcopy(attrs)
@@ -1479,8 +1487,13 @@
@rtype: list
"""
if not base: base = self.baseUsersDN
- if (pattern==''): searchFilter = "uid=*"
- else: searchFilter = pattern
+ # kerberos -> search only PosixAccount
+ if (pattern==''): searchFilter = "(&(objectClass=posixAccount)(uid=*))"
+ elif pattern[0] == '(':
+ searchFilter = "(&(objectClass=posixAccount)%s)" % (pattern)
+ else:
+ searchFilter = "(&(objectClass=posixAccount)(%s))" % (pattern)
+ #
monoattrs = ["uid", "sn", "givenName", "mail"]
result_set = self.search(searchFilter, base, monoattrs + ["telephoneNumber", "loginShell", "objectClass"], ldap.SCOPE_ONELEVEL)
diff -Naur mmc-core-3.0.0.orig/agent/mmc/plugins/kerberos/__init__.py mmc-core-3.0.0/agent/mmc/plugins/kerberos/__init__.py
--- mmc-core-3.0.0.orig/agent/mmc/plugins/kerberos/__init__.py 1970-01-01 00:00:00.000000000 +0000
+++ mmc-core-3.0.0/agent/mmc/plugins/kerberos/__init__.py 2010-05-01 12:06:44.132623770 +0000
@@ -0,0 +1,180 @@
+# -*- coding: utf-8; -*-
+#
+# (c) 2004-2007 Linbox / Free&ALter Soft, http://linbox.com
+# (c) 2007 Mandriva, http://www.mandriva.com/
+# (c) 2007 Kids-und-Co g.e.V http://www.kids-und-co.de
+#
+# $Id: __init__.py 108 2007-11-21 09:56:21Z iosifb $
+#
+# This file is part of Mandriva Management Console (MMC).
+#
+# MMC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# MMC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with MMC; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import logging
+import ldap.modlist
+import copy
+from mmc.plugins.base import ldapUserGroupControl
+import xmlrpclib
+from mmc.support.errorObj import errorMessage
+from mmc.support.mmcException import *
+from mmc.support import mmctools
+import mmc.plugins.base
+from mmc.support.config import *
+from mmc.plugins.base import ldapUserGroupControl
+
+VERSION = "2.3.1"
+APIVERSION = "4:2:0"
+REVISION = int("$Rev: 108 $".split(':')[1].strip(' $'))
+
+def getVersion(): return VERSION
+def getApiVersion(): return APIVERSION
+def getRevision(): return REVISION
+
+def activate():
+ """
+ this function define if the module "base" can be activated.
+ @return: return True if this module can be activate
+ @rtype: boolean
+ """
+ config = KerberosConfig("kerberos")
+ logger = logging.getLogger()
+
+ if config.disabled:
+ logger.info("Kerberos plugin disabled by configuration.")
+ return False
+
+ try:
+ ldapObj = ldapUserGroupControl()
+ except ldap.INVALID_CREDENTIALS:
+ logger.error("Can't bind to LDAP: invalid credentials.")
+ return False
+
+ # Test if the Kerberos LDAP schema is available in the directory
+ try:
+ schema = ldapObj.getSchema("krb5KDCEntry")
+ if len(schema) <= 0:
+ logger.error("Kerberos schema is not included in LDAP directory");
+ return False
+ except:
+ logger.exception("invalid schema")
+ return False
+ try:
+ schema = ldapObj.getSchema("krb5Principal")
+ if len(schema) <= 0:
+ logger.error("Kerberos schema is not included in LDAP directory");
+ return False
+ except:
+ logger.exception("invalid schema")
+ return False
+ """
+ TODO: Check kerberos database
+ """
+ return True
+
+def isKrbUser(uid):
+ return kerberosLdapControl().isKerberosUser(uid)
+
+def addKrbAttr(uid,password):
+ return kerberosLdapControl().addKerberosAttr(uid,password)
+
+def delKrbAttr(uid,password):
+ return kerberosLdapControl().delKerberosAttr(uid,password)
+
+def changePassword(uid,password):
+ return kerberosLdapControl().changePassword(uid, password)
+
+class KerberosConfig(PluginConfig):
+ def __init__(self,name, conffile = None):
+ PluginConfig.__init__(self,name, conffile = None)
+ self.setDefault()
+ self.readConfig()
+
+ def readConfig(self):
+ PluginConfig.readConf(self)
+ self.realm = self.get("kerberos", "realm")
+
+class kerberosLdapControl(mmc.plugins.base.ldapUserGroupControl):
+
+ def __init__(self, conffile = None, conffilebase = None):
+ mmc.plugins.base.ldapUserGroupControl.__init__(self, conffilebase)
+ self.configKerberos = KerberosConfig("kerberos", conffile)
+ self.realm = self.configKerberos.realm
+
+ def delKerberosAttr(self,uid,password):
+ # If the password has been encoded in the XML-RPC stream, decode it
+ if isinstance(password, xmlrpclib.Binary):
+ password = str(password)
+ dn = 'uid=' + uid + ',' + self.baseUsersDN
+ s = self.l.search_s(dn, ldap.SCOPE_BASE)
+ c, attr = s[0]
+ old = {}
+ new = {}
+ for key in attr.keys(): old[key.lower()] = attr[key]
+ new = copy.deepcopy(old)
+ # remove krb attributes
+ new.pop('krb5kdcflags')
+ new.pop('krb5principalname')
+ new.pop('krb5keyversionnumber')
+ try: new.pop('krb5key')
+ except KeyError: pass
+ newobjclasses = ()
+ for s in new.pop('objectclass'):
+ if s[0:4] == 'krb5': pass
+ else: newobjclasses = newobjclasses + (s,)
+ new['objectclass'] = newobjclasses
+ modlist = ldap.modlist.modifyModlist(old, new)
+ #logger = logging.getLogger()
+ #logger.debug(newobjclasses)
+ #logger.debug(modlist)
+ self.l.modify_s(dn, modlist)
+ mmc.plugins.base.ldapUserGroupControl.changeUserPasswd(self,uid,password)
+ return True
+
+ def addKerberosAttr(self,uid,password):
+ # If the password has been encoded in the XML-RPC stream, decode it
+ if isinstance(password, xmlrpclib.Binary):
+ password = str(password)
+ dn = 'uid=' + uid + ',' + self.baseUsersDN
+ s = self.l.search_s(dn, ldap.SCOPE_BASE)
+ c, attr = s[0]
+ old = {}
+ new = {}
+ for key in attr.keys(): old[key.lower()] = attr[key]
+ new = copy.deepcopy(old)
+ new['objectclass'] = new['objectclass'] + ['krb5Principal','krb5KDCEntry']
+ new['userpassword'] = ['{K5Key}']
+ new['krb5kdcflags'] = ['126']
+ new['krb5keyversionnumber'] = ['0']
+ new['krb5principalname'] = [uid+'@' +self.realm]
+ modlist = ldap.modlist.modifyModlist(old, new)
+ self.l.modify_s(dn, modlist)
+ self.l.passwd_s(dn, None, password)
+ return True
+
+ def isKerberosUser(self,uid):
+ ret = False
+ if self.existUser(uid): ret = "krb5Principal" in self.getDetailedUser(uid)["objectClass"]
+ return ret
+
+ def changePassword(self,uid,password):
+ # If the password has been encoded in the XML-RPC stream, decode it
+ if isinstance(password, xmlrpclib.Binary):
+ password = str(password)
+ dn = 'uid=' + uid + ',' + self.baseUsersDN
+ self.l.modify_s(dn, [(ldap.MOD_REPLACE,'userPassWord','{K5KEY}')])
+ self.l.passwd_s(dn, None, password)
+ return True
+
+
diff -Naur mmc-core-3.0.0.orig/agent/setup.py mmc-core-3.0.0/agent/setup.py
--- mmc-core-3.0.0.orig/agent/setup.py 2010-05-01 12:06:18.104618663 +0000
+++ mmc-core-3.0.0/agent/setup.py 2010-05-01 12:08:13.270868725 +0000
@@ -33,5 +33,6 @@
maintainer = "Cedric Delfosse",
maintainer_email = "cdelfosse@mandriva.com",
packages = ["mmc", "mmc.support", "mmc.plugins", "mmc.plugins.base",
- "mmc.plugins.ppolicy", "mmc.core", "mmc.core.audit"],
+ "mmc.plugins.ppolicy", "mmc.core", "mmc.core.audit",
+ "mmc.plugins.kerberos"],
)
diff -Naur mmc-core-3.0.0.orig/conf/plugins/kerberos.ini mmc-core-3.0.0/conf/plugins/kerberos.ini
--- mmc-core-3.0.0.orig/conf/plugins/kerberos.ini 1970-01-01 00:00:00.000000000 +0000
+++ mmc-core-3.0.0/conf/plugins/kerberos.ini 2010-05-01 12:06:38.209871794 +0000
@@ -0,0 +1,5 @@
+[main]
+disable = 0
+
+[kerberos]
+realm = EXAMPLE.COM