|
30 |
# /usr/share/common-licenses/AGPL-3; if not, see |
30 |
# /usr/share/common-licenses/AGPL-3; if not, see |
31 |
# <http://www.gnu.org/licenses/>. |
31 |
# <http://www.gnu.org/licenses/>. |
32 |
|
32 |
|
33 |
from ldap.filter import filter_format |
|
|
34 |
|
35 |
from univention.admin.layout import Tab, Group |
33 |
from univention.admin.layout import Tab, Group |
36 |
import univention.admin.filter |
34 |
import univention.admin.filter |
37 |
import univention.admin.handlers |
35 |
import univention.admin.handlers |
38 |
import univention.admin.password |
|
|
39 |
import univention.admin.allocators |
40 |
import univention.admin.localization |
36 |
import univention.admin.localization |
41 |
import univention.admin.uldap |
|
|
42 |
import univention.admin.nagios as nagios |
37 |
import univention.admin.nagios as nagios |
43 |
import univention.admin.handlers.dns.forward_zone |
38 |
from univention.admin.handlers.computers.base import computerBase |
44 |
import univention.admin.handlers.dns.reverse_zone |
|
|
45 |
import univention.admin.handlers.groups.group |
46 |
import univention.admin.handlers.networks.network |
47 |
import time |
48 |
|
39 |
|
49 |
translation=univention.admin.localization.translation('univention.admin.handlers.computers') |
40 |
translation=univention.admin.localization.translation('univention.admin.handlers.computers') |
50 |
_=translation.translate |
41 |
_=translation.translate |
|
386 |
mapping.register('name', 'cn', None, univention.admin.mapping.ListToString) |
377 |
mapping.register('name', 'cn', None, univention.admin.mapping.ListToString) |
387 |
mapping.register('description', 'description', None, univention.admin.mapping.ListToString) |
378 |
mapping.register('description', 'description', None, univention.admin.mapping.ListToString) |
388 |
mapping.register('domain', 'associatedDomain', None, univention.admin.mapping.ListToString) |
379 |
mapping.register('domain', 'associatedDomain', None, univention.admin.mapping.ListToString) |
389 |
mapping.register('inventoryNumber', 'univentionInventoryNumber') |
|
|
390 |
mapping.register('serverRole', 'univentionServerRole') |
380 |
mapping.register('serverRole', 'univentionServerRole') |
391 |
mapping.register('mac', 'macAddress' ) |
381 |
mapping.register('mac', 'macAddress' ) |
|
|
382 |
mapping.register('inventoryNumber', 'univentionInventoryNumber') |
392 |
mapping.register('reinstall', 'univentionServerReinstall', None, univention.admin.mapping.ListToString) |
383 |
mapping.register('reinstall', 'univentionServerReinstall', None, univention.admin.mapping.ListToString) |
393 |
mapping.register('instprofile', 'univentionServerInstallationProfile', None, univention.admin.mapping.ListToString) |
384 |
mapping.register('instprofile', 'univentionServerInstallationProfile', None, univention.admin.mapping.ListToString) |
394 |
mapping.register('reinstalloption', 'univentionServerInstallationOption', None, univention.admin.mapping.ListToString) |
385 |
mapping.register('reinstalloption', 'univentionServerInstallationOption', None, univention.admin.mapping.ListToString) |
|
403 |
nagios.addPropertiesMappingOptionsAndLayout(property_descriptions, mapping, options, layout) |
394 |
nagios.addPropertiesMappingOptionsAndLayout(property_descriptions, mapping, options, layout) |
404 |
|
395 |
|
405 |
|
396 |
|
406 |
class object(univention.admin.handlers.simpleComputer, nagios.Support): |
397 |
class object(computerBase): |
407 |
module=module |
398 |
module=module |
408 |
|
399 |
mapping = mapping |
409 |
def __init__(self, co, lo, position, dn='', superordinate=None, attributes = [] ): |
400 |
CONFIG_NAME = 'univentionDefaultMemberserverGroup' |
410 |
univention.admin.handlers.simpleComputer.__init__(self, co, lo, position, dn, superordinate, attributes) |
401 |
DEFAULT_OCS = ['top', 'person', 'univentionHost', 'univentionMemberServer'] |
411 |
nagios.Support.__init__(self) |
402 |
SAMBA_ACCOUNT_FLAG = 'W' |
412 |
|
403 |
SERVER_TYPE = 'univentionMemberServer' |
413 |
def open(self): |
404 |
SERVER_ROLE = 'member' |
414 |
univention.admin.handlers.simpleComputer.open( self ) |
405 |
|
415 |
self.nagios_open() |
406 |
rewrite = object.rewrite |
416 |
|
407 |
lookup_filter = object.lookup_filter |
417 |
self.modifypassword=0 |
408 |
lookup = object.lookup |
418 |
if self.exists(): |
409 |
identify = object.identify |
419 |
userPassword=self.oldattr.get('userPassword',[''])[0] |
|
|
420 |
if userPassword: |
421 |
self.info['password']=userPassword |
422 |
self.modifypassword=0 |
423 |
if self.exists(): |
424 |
|
425 |
if 'posix' in self.options and not self.info.get( 'primaryGroup' ): |
426 |
primaryGroupNumber=self.oldattr.get('gidNumber',[''])[0] |
427 |
univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'primary group number = %s' % (primaryGroupNumber)) |
428 |
if primaryGroupNumber: |
429 |
primaryGroupResult=self.lo.searchDn(filter_format('(&(objectClass=posixGroup)(gidNumber=%s))', [primaryGroupNumber])) |
430 |
if primaryGroupResult: |
431 |
self['primaryGroup']=primaryGroupResult[0] |
432 |
univention.debug.debug(univention.debug.ADMIN, univention.debug.INFO, 'Set primary group = %s' % (self['primaryGroup'])) |
433 |
else: |
434 |
self['primaryGroup']=None |
435 |
self.save() |
436 |
raise univention.admin.uexceptions.primaryGroup |
437 |
else: |
438 |
self['primaryGroup']=None |
439 |
self.save() |
440 |
raise univention.admin.uexceptions.primaryGroup |
441 |
if 'samba' in self.options: |
442 |
sid = self.oldattr.get('sambaSID', [''])[0] |
443 |
pos = sid.rfind('-') |
444 |
self.info['sambaRID'] = sid[pos+1:] |
445 |
|
446 |
self.save() |
447 |
else: |
448 |
self.modifypassword=0 |
449 |
if 'posix' in self.options: |
450 |
res=univention.admin.config.getDefaultValue(self.lo, 'univentionDefaultMemberserverGroup', position=self.position) |
451 |
if res: |
452 |
self['primaryGroup']=res |
453 |
|
454 |
def _ldap_pre_create(self): |
455 |
super(object, self)._ldap_pre_create() |
456 |
if not self['password']: |
457 |
self['password']=self.oldattr.get('password',[''])[0] |
458 |
self.modifypassword=0 |
459 |
|
460 |
def _ldap_addlist(self): |
461 |
ocs=['top', 'person', 'univentionHost', 'univentionMemberServer'] |
462 |
al=[] |
463 |
if 'kerberos' in self.options: |
464 |
domain=univention.admin.uldap.domain(self.lo, self.position) |
465 |
realm=domain.getKerberosRealm() |
466 |
|
467 |
if realm: |
468 |
al.append(('krb5MaxLife', '86400')) |
469 |
al.append(('krb5MaxRenew', '604800')) |
470 |
al.append(('krb5KDCFlags', '126')) |
471 |
krb_key_version=str(int(self.oldattr.get('krb5KeyVersionNumber', ['0'])[0])+1) |
472 |
al.append(('krb5KeyVersionNumber', self.oldattr.get('krb5KeyVersionNumber', []), krb_key_version)) |
473 |
else: |
474 |
# can't do kerberos |
475 |
self._remove_option( 'kerberos' ) |
476 |
if 'posix' in self.options: |
477 |
self.uidNum=univention.admin.allocators.request(self.lo, self.position, 'uidNumber') |
478 |
self.alloc.append(('uidNumber',self.uidNum)) |
479 |
gidNum = self.get_gid_for_primary_group() |
480 |
al.append(('uidNumber', [self.uidNum])) |
481 |
al.append(('gidNumber', [gidNum])) |
482 |
|
483 |
if self.modifypassword or self['password']: |
484 |
if 'kerberos' in self.options: |
485 |
krb_keys=univention.admin.password.krb5_asn1(self.krb5_principal(), self['password']) |
486 |
al.append(('krb5Key', self.oldattr.get('password', ['1']), krb_keys)) |
487 |
if 'posix' in self.options: |
488 |
password_crypt = "{crypt}%s" % (univention.admin.password.crypt(self['password'])) |
489 |
al.append(('userPassword', self.oldattr.get('userPassword', [''])[0], password_crypt)) |
490 |
if 'samba' in self.options: |
491 |
password_nt, password_lm = univention.admin.password.ntlm(self['password']) |
492 |
al.append(('sambaNTPassword', self.oldattr.get('sambaNTPassword', [''])[0], password_nt)) |
493 |
al.append(('sambaLMPassword', self.oldattr.get('sambaLMPassword', [''])[0], password_lm)) |
494 |
sambaPwdLastSetValue = str(long(time.time())) |
495 |
al.append(('sambaPwdLastSet', self.oldattr.get('sambaPwdLastSet', [''])[0], sambaPwdLastSetValue)) |
496 |
self.modifypassword=0 |
497 |
if 'samba' in self.options: |
498 |
acctFlags=univention.admin.samba.acctFlags(flags={'W':1}) |
499 |
if self.s4connector_present: |
500 |
# In this case Samba 4 must create the SID, the s4 connector will sync the |
501 |
# new sambaSID back from Samba 4. |
502 |
self.machineSid='S-1-4-%s' % self.uidNum |
503 |
else: |
504 |
self.machineSid = self.getMachineSid(self.lo, self.position, self.uidNum, self.get('sambaRID')) |
505 |
self.alloc.append(('sid',self.machineSid)) |
506 |
al.append(('sambaSID', [self.machineSid])) |
507 |
al.append(('sambaAcctFlags', [acctFlags.decode()])) |
508 |
al.append(('displayName', self.info['name'])) |
509 |
|
510 |
al.insert(0, ('objectClass', ocs)) |
511 |
al.append(('univentionServerRole', '', 'member')) |
512 |
return al |
513 |
|
514 |
def _ldap_post_create(self): |
515 |
if 'posix' in self.options: |
516 |
if hasattr(self, 'uid') and self.uid: |
517 |
univention.admin.allocators.confirm(self.lo, self.position, 'uid', self.uid) |
518 |
univention.admin.handlers.simpleComputer.primary_group( self ) |
519 |
univention.admin.handlers.simpleComputer.update_groups( self ) |
520 |
univention.admin.handlers.simpleComputer._ldap_post_create( self ) |
521 |
self.nagios_ldap_post_create() |
522 |
|
523 |
def _ldap_pre_remove(self): |
524 |
self.open() |
525 |
if 'posix' in self.options and self.oldattr.get( 'uidNumber' ): |
526 |
self.uidNum=self.oldattr['uidNumber'][0] |
527 |
|
528 |
def _ldap_post_remove(self): |
529 |
if 'posix' in self.options: |
530 |
univention.admin.allocators.release(self.lo, self.position, 'uidNumber', self.uidNum) |
531 |
groupObjects=univention.admin.handlers.groups.group.lookup(self.co, self.lo, filter_s=filter_format('uniqueMember', [self.dn])) |
532 |
if groupObjects: |
533 |
for i in range(0, len(groupObjects)): |
534 |
groupObjects[i].open() |
535 |
if self.dn in groupObjects[i]['users']: |
536 |
groupObjects[i]['users'].remove(self.dn) |
537 |
groupObjects[i].modify(ignore_license=1) |
538 |
|
539 |
self.nagios_ldap_post_remove() |
540 |
univention.admin.handlers.simpleComputer._ldap_post_remove( self ) |
541 |
# Need to clean up oldinfo. If remove was invoked, because the |
542 |
# creation of the object has failed, the next try will result in |
543 |
# a 'object class violation' (Bug #19343) |
544 |
self.oldinfo = {} |
545 |
|
546 |
def krb5_principal(self): |
547 |
domain=univention.admin.uldap.domain(self.lo, self.position) |
548 |
realm=domain.getKerberosRealm() |
549 |
if self.info.has_key('domain') and self.info['domain']: |
550 |
kerberos_domain=self.info['domain'] |
551 |
else: |
552 |
kerberos_domain=domain.getKerberosRealm() |
553 |
return 'host/' + self['name']+'.'+kerberos_domain.lower()+'@'+realm |
554 |
|
555 |
def _ldap_post_modify(self): |
556 |
univention.admin.handlers.simpleComputer.primary_group( self ) |
557 |
univention.admin.handlers.simpleComputer.update_groups( self ) |
558 |
univention.admin.handlers.simpleComputer._ldap_post_modify( self ) |
559 |
self.nagios_ldap_post_modify() |
560 |
|
561 |
def _ldap_pre_modify(self): |
562 |
if self.hasChanged('password'): |
563 |
if not self['password']: |
564 |
self['password']=self.oldattr.get('password',[''])[0] |
565 |
self.modifypassword=0 |
566 |
elif not self.info['password']: |
567 |
self['password']=self.oldattr.get('password',[''])[0] |
568 |
self.modifypassword=0 |
569 |
else: |
570 |
self.modifypassword=1 |
571 |
self.nagios_ldap_pre_modify() |
572 |
univention.admin.handlers.simpleComputer._ldap_pre_modify( self ) |
573 |
|
574 |
|
575 |
def _ldap_modlist(self): |
576 |
ml=univention.admin.handlers.simpleComputer._ldap_modlist( self ) |
577 |
|
578 |
self.nagios_ldap_modlist(ml) |
579 |
|
580 |
if self.hasChanged('name'): |
581 |
if 'posix' in self.options: |
582 |
if hasattr(self, 'uidNum'): |
583 |
univention.admin.allocators.confirm(self.lo, self.position, 'uidNumber', self.uidNum) |
584 |
requested_uid="%s$" % self['name'] |
585 |
try: |
586 |
self.uid=univention.admin.allocators.request(self.lo, self.position, 'uid', value=requested_uid) |
587 |
except Exception: |
588 |
self.cancel() |
589 |
raise univention.admin.uexceptions.uidAlreadyUsed, ': %s' % requested_uid |
590 |
return [] |
591 |
|
592 |
self.alloc.append(('uid',self.uid)) |
593 |
|
594 |
ml.append(('uid', self.oldattr.get('uid', [None])[0], self.uid)) |
595 |
|
596 |
if 'samba' in self.options: |
597 |
ml.append(('displayName', self.oldattr.get('displayName', [None])[0], self['name'])) |
598 |
|
599 |
if 'kerberos' in self.options: |
600 |
ml.append(('krb5PrincipalName', self.oldattr.get('krb5PrincipalName', []), [self.krb5_principal()])) |
601 |
|
602 |
if self.modifypassword and self['password']: |
603 |
if 'kerberos' in self.options: |
604 |
krb_keys=univention.admin.password.krb5_asn1(self.krb5_principal(), self['password']) |
605 |
krb_key_version=str(int(self.oldattr.get('krb5KeyVersionNumber', ['0'])[0])+1) |
606 |
ml.append(('krb5Key', self.oldattr.get('password', ['1']), krb_keys)) |
607 |
ml.append(('krb5KeyVersionNumber', self.oldattr.get('krb5KeyVersionNumber', []), krb_key_version)) |
608 |
if 'posix' in self.options: |
609 |
password_crypt = "{crypt}%s" % (univention.admin.password.crypt(self['password'])) |
610 |
ml.append(('userPassword', self.oldattr.get('userPassword', [''])[0], password_crypt)) |
611 |
if 'samba' in self.options: |
612 |
password_nt, password_lm = univention.admin.password.ntlm(self['password']) |
613 |
ml.append(('sambaNTPassword', self.oldattr.get('sambaNTPassword', [''])[0], password_nt)) |
614 |
ml.append(('sambaLMPassword', self.oldattr.get('sambaLMPassword', [''])[0], password_lm)) |
615 |
sambaPwdLastSetValue = str(long(time.time())) |
616 |
ml.append(('sambaPwdLastSet', self.oldattr.get('sambaPwdLastSet', [''])[0], sambaPwdLastSetValue)) |
617 |
|
618 |
# add samba option |
619 |
if self.exists() and self.option_toggled('samba') and 'samba' in self.options: |
620 |
acctFlags=univention.admin.samba.acctFlags(flags={'W':1}) |
621 |
if self.s4connector_present: |
622 |
# In this case Samba 4 must create the SID, the s4 connector will sync the |
623 |
# new sambaSID back from Samba 4. |
624 |
self.machineSid='S-1-4-%s' % self.oldattr['uidNumber'][0] |
625 |
else: |
626 |
self.machineSid = self.getMachineSid(self.lo, self.position, self.oldattr['uidNumber'][0], self.get('sambaRID')) |
627 |
self.alloc.append(('sid',self.machineSid)) |
628 |
ml.append(('sambaSID', '', [self.machineSid])) |
629 |
ml.append(('sambaAcctFlags', '', [acctFlags.decode()])) |
630 |
ml.append(('displayName', '', self.info['name'])) |
631 |
sambaPwdLastSetValue = str(long(time.time())) |
632 |
ml.append(('sambaPwdLastSet', self.oldattr.get('sambaPwdLastSet', [''])[0], sambaPwdLastSetValue)) |
633 |
if self.exists() and self.option_toggled('samba') and 'samba' not in self.options: |
634 |
for key in [ 'sambaSID', 'sambaAcctFlags', 'sambaNTPassword', 'sambaLMPassword', 'sambaPwdLastSet', 'displayName' ]: |
635 |
if self.oldattr.get(key, []): |
636 |
ml.insert(0, (key, self.oldattr.get(key, []), '')) |
637 |
|
638 |
if self.hasChanged('sambaRID') and not hasattr(self, 'machineSid'): |
639 |
self.machineSid = self.getMachineSid(self.lo, self.position, self.oldattr['uidNumber'][0], self.get('sambaRID')) |
640 |
ml.append(('sambaSID', self.oldattr.get('sambaSID', ['']), [self.machineSid])) |
641 |
|
642 |
return ml |
643 |
|
644 |
def cleanup(self): |
645 |
self.open() |
646 |
self.nagios_cleanup() |
647 |
univention.admin.handlers.simpleComputer.cleanup( self ) |
648 |
|
649 |
def cancel(self): |
650 |
for i,j in self.alloc: |
651 |
univention.debug.debug(univention.debug.ADMIN, univention.debug.WARN, 'cancel: release (%s): %s' % (i,j) ) |
652 |
univention.admin.allocators.release(self.lo, self.position, i, j) |
653 |
|
654 |
def link(self): |
655 |
result = [] |
656 |
if self['ip'] and len( self[ 'ip' ] ) > 0 and self['ip'][ 0 ]: |
657 |
result = [{ 'url': 'https://%s/univention-management-console/' % self['ip'][ 0 ], |
658 |
'ipaddr': self['ip'][ 0 ], |
659 |
}] |
660 |
if self.has_key('dnsEntryZoneForward') and self['dnsEntryZoneForward'] and len( self['dnsEntryZoneForward' ] ) > 0: |
661 |
zone = univention.admin.uldap.explodeDn( self['dnsEntryZoneForward'][0], 1)[0] |
662 |
if not result: |
663 |
result = [ { 'url': 'https://%s.%s/univention-management-console/' % (self['name'], zone) }] |
664 |
result[0]['fqdn'] = '%s.%s' % (self['name'], zone) |
665 |
if result: |
666 |
result[0]['name'] = _('Open Univention Management Console on this computer') |
667 |
return result |
668 |
return None |
669 |
|
670 |
def rewrite(filter, mapping): |
671 |
if filter.variable == 'ip': |
672 |
filter.variable='aRecord' |
673 |
else: |
674 |
univention.admin.mapping.mapRewrite(filter, mapping) |
675 |
|
676 |
def lookup_filter(filter_s=None, lo=None): |
677 |
filter_s = univention.admin.filter.replace_fqdn_filter( filter_s ) |
678 |
if str(filter_s).find('(dnsAlias=') != -1: |
679 |
filter_s = univention.admin.handlers.dns.alias.lookup_alias_filter(lo, filter_s) |
680 |
if filter_s: |
681 |
return lookup_filter(filter_s, lo) |
682 |
else: |
683 |
return None |
684 |
lookup_filter_obj = \ |
685 |
univention.admin.filter.conjunction('&', [ |
686 |
univention.admin.filter.expression('objectClass', 'univentionHost'), |
687 |
univention.admin.filter.expression('objectClass', 'univentionMemberServer'), |
688 |
]) |
689 |
|
690 |
# ATTENTION: has its own rewrite function. |
691 |
lookup_filter_obj.append_unmapped_filter_string(filter_s, rewrite, mapping) |
692 |
return lookup_filter_obj |
693 |
|
694 |
def lookup(co, lo, filter_s, base='', superordinate=None, scope='sub', unique=0, required=0, timeout=-1, sizelimit=0): |
695 |
|
696 |
filter=lookup_filter(filter_s, lo) |
697 |
if filter is None: |
698 |
return [] |
699 |
res=[] |
700 |
for dn, attrs in lo.search(unicode(filter), base, scope, [], unique, required, timeout, sizelimit): |
701 |
res.append( object( co, lo, None, dn, attributes = attrs ) ) |
702 |
return res |
703 |
|
704 |
def identify(dn, attr, canonical=0): |
705 |
return 'univentionHost' in attr.get('objectClass', []) and 'univentionMemberServer' in attr.get('objectClass', []) |