def syncrepl_entry(self, dn, attrs, uuid): attrs = utils.normalize(attrs) if uuid in self.__db: odn = self.__db[uuid] if odn != dn: if not self.callback == None: self.callback(change_type='moddn', previous_dn=odn, change_number=None, dn=dn, entry=attrs) else: if not self.callback == None: self.callback(change_type='modify', previous_dn=None, change_number=None, dn=self.__db[uuid], entry=attrs) else: if not self.callback == None: self.callback(change_type='add', previous_dn=None, change_number=None, dn=dn, entry=attrs) self.__db[uuid] = dn
def _synchronize(*args, **kw): log.info( _("Worker process %s handling %s") % (multiprocessing.current_process().name, kw['dn'])) entry = utils.normalize(kw) if not entry.has_key('mail'): return if not 'kolabinetorgperson' in entry['objectclass']: return imap = IMAP() imap.connect() if not imap.user_mailbox_exists(entry['mail']): if entry.has_key('mailhost'): server = entry['mailhost'] else: server = None imap.user_mailbox_create(entry['mail'], server=server) imap.disconnect()
def test_001_normalize(self): attr = {"test1": " trim ", "test2": [" trim1 ", " trim2 "]} result = utils.normalize(attr) self.assertEqual(result['test1'], "trim") self.assertEqual(result['test2'][0], "trim1") self.assertEqual(result['test2'][1], "trim2")
def set_secondary_mail(self, *args, **kw): """ The arguments passed to the 'set_user_attrs_alternative_mail' hook: primary_mail - the policy user_attrs - the current user attributes primary_domain - the domain to use in the primary mail attribute secondary_domains - the secondary domains that are aliases Return a list of secondary mail addresses """ user_attrs = utils.normalize(kw['entry']) if not user_attrs.has_key('domain'): user_attrs['domain'] = kw['primary_domain'] elif not user_attrs['domain'] == kw['primary_domain']: user_attrs['domain'] = kw['primary_domain'] if not user_attrs.has_key('preferredlanguage'): default_locale = conf.get(user_attrs['domain'], 'default_locale') if default_locale == None: default_locale = conf.get(user_attrs['domain'], 'default_locale') if default_locale == None: default_locale = 'en_US' user_attrs['preferredlanguage'] = default_locale try: exec("alternative_mail_routines = %s" % kw['secondary_mail']) except Exception, e: log.error(_("Could not parse the alternative mail routines"))
def set_primary_mail(self, *args, **kw): """ The arguments passed to the 'set_user_attrs_mail' hook: primary_mail - the policy user_attrs - the current user attributes primary_domain - the domain to use in the primary mail attribute secondary_domains - the secondary domains that are aliases Return the new primary mail address """ user_attrs = utils.normalize(kw['entry']) if not user_attrs.has_key('domain'): user_attrs['domain'] = kw['primary_domain'] elif not user_attrs['domain'] == kw['primary_domain']: user_attrs['domain'] = kw['primary_domain'] if not user_attrs.has_key('preferredlanguage'): default_locale = conf.get(user_attrs['domain'], 'default_locale') if default_locale == None: default_locale = conf.get('kolab', 'default_locale') if default_locale == None: default_locale = 'en_US' user_attrs['preferredlanguage'] = default_locale try: mail = kw['primary_mail'] % user_attrs mail = utils.translate(mail, user_attrs['preferredlanguage']) mail = mail.lower() return mail except KeyError, e: log.warning( _("Attribute substitution for 'mail' failed in Recipient Policy" )) if user_attrs.has_key('mail'): return user_attrs['mail'] else: return None
def set_primary_mail(self, *args, **kw): """ The arguments passed to the 'set_user_attrs_mail' hook: primary_mail - the policy user_attrs - the current user attributes primary_domain - the domain to use in the primary mail attribute secondary_domains - the secondary domains that are aliases Return the new primary mail address """ user_attrs = utils.normalize(kw['entry']) if not user_attrs.has_key('domain'): user_attrs['domain'] = kw['primary_domain'] elif not user_attrs['domain'] == kw['primary_domain']: user_attrs['domain'] = kw['primary_domain'] if not user_attrs.has_key('preferredlanguage'): default_locale = conf.get(user_attrs['domain'], 'default_locale') if default_locale == None: default_locale = conf.get('kolab', 'default_locale') if default_locale == None: default_locale = 'en_US' user_attrs['preferredlanguage'] = default_locale try: mail = kw['primary_mail'] % user_attrs mail = utils.translate(mail, user_attrs['preferredlanguage']) mail = mail.lower() return mail except KeyError, e: log.warning(_("Attribute substitution for 'mail' failed in Recipient Policy")) if user_attrs.has_key('mail'): return user_attrs['mail'] else: return None
def _synchronize(*args, **kw): log.info(_("Worker process %s handling %s") % (multiprocessing.current_process().name, kw['dn'])) entry = utils.normalize(entry) if not entry.has_key('mail'): return if not 'kolabinetorgperson' in entry['objectclass']: return imap = IMAP() imap.connect() if not imap.user_mailbox_exists(entry['mail']): if entry.has_key('mailhost'): server = entry['mailhost'] else: server = None imap.user_mailbox_create(entry['mail'], server=server) imap.disconnect()
def syncrepl_entry(self, dn, attrs, uuid): attrs = utils.normalize(attrs) if uuid in self.__db: odn = self.__db[uuid] if odn != dn: if not self.callback == None: self.callback( change_type='moddn', previous_dn=odn, change_number=None, dn=dn, entry=attrs ) else: if not self.callback == None: self.callback( change_type='modify', previous_dn=None, change_number=None, dn=self.__db[uuid], entry=attrs ) else: if not self.callback == None: self.callback( change_type='add', previous_dn=None, change_number=None, dn=dn, entry=attrs ) self.__db[uuid] = dn
def handler(*args, **kw): auth = Auth() auth.connect() if len(args) == 4: # moddn, not relevant for Sieve Script Management pass elif len(args) == 3: dn = args[0] new = utils.normalize(args[1]) old = utils.normalize(args[2]) if isinstance(old, dict) and len(old.keys()) > 0: # Either the entry changed or was deleted if isinstance(new, dict) and len(new.keys()) > 0: # The entry was modified. result_attr = conf.get('cyrus-sasl', 'result_attribute') if result_attr not in new: log.error("Entry %r does not have attribute %r" % (dn, result_attr)) return # See if the mailserver_attribute exists mailserver_attribute = conf.get( 'ldap', 'mailserver_attribute').lower() if mailserver_attribute is None: log.error("Mail server attribute is not set") # TODO: Perhaps, query for IMAP servers. If there is only one, # we know what to do. return if mailserver_attribute in new: if not new[mailserver_attribute] == constants.fqdn: log.info( "The mail server for user %r is set, and it is not me (%r)" % (dn, new[mailserver_attribute])) return else: log.error("Entry %r does not have a mail server set" % (dn)) return conf.plugins.exec_hook('sieve_mgmt_refresh', kw={'user': new[result_attr]}) else: # The entry was deleted. This is irrelevant for # Sieve Script Management return elif isinstance(new, dict) and len(new.keys()) > 0: # Old is not a dict (or empty), so the entry is just created # See if the mailserver_attribute exists mailserver_attribute = conf.get('ldap', 'mailserver_attribute').lower() result_attr = conf.get('cyrus-sasl', 'result_attribute').lower() if mailserver_attribute is None: log.error("Mail server attribute is not set") # TODO: Perhaps, query for IMAP servers. If there is only one, # we know what to do. return if mailserver_attribute in new: if not new[mailserver_attribute] == constants.fqdn: log.info( "The mail server for user %r is set, and it is not me (%r)" % (dn, new[mailserver_attribute])) return conf.plugins.exec_hook('sieve_mgmt_refresh', kw={'user': new[result_attr]}) else: log.info("entry %r changed, but no new or old attributes" % (dn))
def verify_delegate(self): """ Verify whether the authenticated user is a delegate of the envelope sender. """ if self.sender_domain == None: if len(self.sender.split('@')) > 1: self.sender_domain = self.sender.split('@')[1] else: self.sender_domain = conf.get('kolab', 'primary_domain') if self.sender == self.sasl_username: return True search_attrs = conf.get_list(self.sender_domain, 'mail_attributes') if search_attrs == None: search_attrs = conf.get_list( conf.get('kolab', 'auth_mechanism'), 'mail_attributes' ) sender_users = self.auth.find_recipient( self.sender, domain=self.sender_domain ) if isinstance(sender_users, list): if len(sender_users) > 1: # More then one sender user with this recipient address. # TODO: check each of the sender users found. self.sender_user = { 'dn': sender_users[0] } elif len(sender_users) == 1: self.sender_user = { 'dn': sender_users } else: self.sender_user = { 'dn': False } elif isinstance(sender_users, basestring): self.sender_user = { 'dn': sender_users } if not self.sender_user['dn']: cache_update( function='verify_sender', sender=self.sender, recipients=self.recipients, result=(int)(False), sasl_username=self.sasl_username, sasl_sender=self.sasl_sender ) reject(_("Could not find envelope sender user %s") % (self.sender)) attrs = search_attrs attrs.extend( [ 'kolabAllowSMTPRecipient', 'kolabAllowSMTPSender', 'kolabDelegate' ] ) user_attrs = self.auth.get_user_attributes( self.sender_domain, self.sender_user, attrs ) user_attrs['dn'] = self.sender_user['dn'] self.sender_user = utils.normalize(user_attrs) if not self.sender_user.has_key('kolabdelegate'): reject( _("%s is unauthorized to send on behalf of %s") % ( self.sasl_user['dn'], self.sender_user['dn'] ) ) elif self.sender_user['kolabdelegate'] == None: # No delegates for this sender could be found. The user is # definitely NOT a delegate of the sender. log.warning( _("User %s attempted to use envelope sender address %s " + \ "without authorization") % ( policy_request["sasl_username"], policy_request["sender"] ) ) # Got a final answer here, do the caching thing. if not cache == False: record_id = cache_update( function='verify_sender', sender=self.sender, recipients=self.recipients, result=(int)(False), sasl_username=self.sasl_username, sasl_sender=self.sasl_sender ) sender_is_delegate = False else: # See if we can match the value of the envelope sender delegates to # the actual sender sasl_username if self.sasl_user == None: sasl_users = self.auth.find_recipient( self.sasl_username, domain=self.sasl_domain ) if isinstance(sasl_users, list): if len(sasl_users) == 0: log.error(_("Could not find recipient")) return False else: self.sasl_user = { 'dn': sasl_users[0] } elif isinstance(sasl_users, basestring): self.sasl_user = { 'dn': sasl_users } # Possible values for the kolabDelegate attribute are: # a 'uid', a 'dn'. if not self.sasl_user.has_key('uid'): self.sasl_user['uid'] = self.auth.get_user_attribute( self.sasl_domain, self.sasl_user, 'uid' ) sender_delegates = self.sender_user['kolabdelegate'] if not type(sender_delegates) == list: sender_delegates = [ sender_delegates ] for sender_delegate in sender_delegates: if self.sasl_user['dn'] == sender_delegate: log.debug( _("Found user %s to be a delegate user of %s") % ( policy_request["sasl_username"], policy_request["sender"] ), level=8 ) sender_is_delegate = True elif self.sasl_user['uid'] == sender_delegate: log.debug( _("Found user %s to be a delegate user of %s") % ( policy_request["sasl_username"], policy_request["sender"] ), level=8 ) sender_is_delegate = True # If nothing matches sender_is_delegate is still None. if not sender_is_delegate == True: sender_is_delegate = False return sender_is_delegate
def verify_authenticity(self): """ Verify that the SASL username or lack thereof corresponds with allowing or disallowing authenticated users. If an SASL username is supplied, use it to obtain the authentication database user object including all attributes we may find ourselves interested in. """ if self.sasl_username == None: if not conf.allow_unauthenticated: reject(_("Unauthorized access not allowed")) else: # If unauthenticated is allowed, I have nothing to do here. return True sasl_username = self.sasl_username # If we have an sasl_username, find the user object in the # authentication database, along with the attributes we are # interested in. if self.sasl_domain == None: if len(self.sasl_username.split('@')) > 1: self.sasl_domain = self.sasl_username.split('@')[1] else: self.sasl_domain = conf.get('kolab', 'primary_domain') sasl_username = "******" % (self.sasl_username, self.sasl_domain) if self.auth == None: self.auth = Auth(self.sasl_domain) elif not self.auth.domain == self.sasl_domain: self.auth = Auth(self.sasl_domain) sasl_users = self.auth.find_recipient( sasl_username, domain=self.sasl_domain ) if isinstance(sasl_users, list): if len(sasl_users) == 0: log.error(_("Could not find recipient")) return False else: self.sasl_user = { 'dn': sasl_users[0] } elif isinstance(sasl_users, basestring): self.sasl_user = { 'dn': sasl_users } if not self.sasl_user['dn']: # Got a final answer here, do the caching thing. cache_update( function='verify_sender', sender=self.sender, recipients=self.recipients, result=(int)(False), sasl_username=self.sasl_username, sasl_sender=self.sasl_sender ) reject( _("Could not find envelope sender user %s") % ( self.sasl_username ) ) attrs = conf.get_list(self.sasl_domain, 'auth_attributes') if attrs == None or (isinstance(attrs, list) and len(attrs) == 0): attrs = conf.get_list( conf.get('kolab', 'auth_mechanism'), 'auth_attributes' ) mail_attrs = conf.get_list(self.sasl_domain, 'mail_attributes') if mail_attrs == None or \ (isinstance(mail_attrs, list) and len(mail_attrs) == 0): mail_attrs = conf.get_list( conf.get('kolab', 'auth_mechanism'), 'mail_attributes' ) if not mail_attrs == None: attrs.extend(mail_attrs) attrs.extend( [ 'kolabAllowSMTPRecipient', 'kolabAllowSMTPSender' ] ) attrs = list(set(attrs)) user_attrs = self.auth.get_user_attributes( self.sasl_domain, self.sasl_user, attrs ) user_attrs['dn'] = self.sasl_user['dn'] self.sasl_user = utils.normalize(user_attrs) log.debug( _("Obtained authenticated user details for %r: %r") % ( self.sasl_user['dn'], self.sasl_user.keys() ), level=8 )
def handler(*args, **kw): log.info("kolab.handler(args(%d): %r, kw: %r)" % (len(args), args, kw)) auth = Auth() auth.connect() if len(args) == 4: # moddn dn = args[0] new = utils.normalize(args[1]) old = utils.normalize(args[2]) command = args[4] pass elif len(args) == 3: dn = args[0] new = utils.normalize(args[1]) old = utils.normalize(args[2]) if isinstance(old, dict) and len(old.keys()) > 0: # Two options: # - entry changed # - entry deleted log.info("user %r, old is dict" % (dn)) if isinstance(new, dict) and len(new.keys()) > 0: log.info("Modify entry %r" % (dn)) mailserver_attribute = conf.get('ldap', 'mailserver_attribute').lower() if mailserver_attribute == None: log.error("Mail server attribute is not set") return if old.has_key(mailserver_attribute): log.info("Modified entry %r has mail server attribute %s: %r" % (dn, mailserver_attribute, new[mailserver_attribute])) if not old[mailserver_attribute] == constants.fqdn: # Even though the new mailserver can be us, it is the # *current* mail server that needs to push for the XFER. log.info("The mail server for user %r is set, and it is not me (%r)" % (dn, old[mailserver_attribute])) return else: # If old has no mailserver attribute, but new does, we need to create # the user locally. if new.has_key(mailserver_attribute): if not new[mailserver_attribute] == constants.fqdn: log.info("The mail server for user %r is set (in new, not old), but it is not me (%r)" % (dn, new[mailserver_attribute])) return else: log.info("Entry %r does not have a mail server attribute." % (dn)) return auth._auth._synchronize_callback( change_type = 'modify', previous_dn = None, change_number = None, dn = dn, entry = new ) else: log.info("Delete entry %r" % (dn)) # See if the mailserver_attribute exists mailserver_attribute = conf.get('ldap', 'mailserver_attribute').lower() if mailserver_attribute == None: log.error("Mail server attribute is not set") # TODO: Perhaps, query for IMAP servers. If there is only one, # we know what to do. return if old.has_key(mailserver_attribute): log.info("Deleted entry %r has mail server attribute %s: %r" % (dn, mailserver_attribute, old[mailserver_attribute])) if not old[mailserver_attribute] == constants.fqdn: log.info("The mail server for user %r is set, and it is not me (%r)" % (dn, old[mailserver_attribute])) return else: log.info("Entry deletion notification for %r does not have a mail server attribute specified." % (dn)) cfg = ConfigRegistry() cfg.load() if cfg.is_true('mail/cyrus/mailbox/delete', True): auth._auth._synchronize_callback( change_type = 'delete', previous_dn = None, change_number = None, dn = dn, entry = old ) elif isinstance(new, dict) and len(new.keys()) > 0: # Old is not a dict (or empty), so the entry is just created log.info("Add entry %r" % (dn)) # See if the mailserver_attribute exists mailserver_attribute = conf.get('ldap', 'mailserver_attribute').lower() if mailserver_attribute == None: log.error("Mail server attribute is not set") # TODO: Perhaps, query for IMAP servers. If there is only one, # we know what to do. return if new.has_key(mailserver_attribute): log.info("Added entry %r has mail server attribute %s: %r" % (dn, mailserver_attribute, new[mailserver_attribute])) if not new[mailserver_attribute] == constants.fqdn: log.info("The mail server for user %r is set, and it is not me (%r)" % (dn, new[mailserver_attribute])) return else: log.info("Added entry %r does not have a mail server attribute set." % (dn)) return auth._auth._synchronize_callback( change_type = 'add', previous_dn = None, change_number = None, dn = dn, entry = new ) else: log.info("entry %r changed, but no new or old attributes" % (dn))
_("Policy for secondary email address failed: %r") % (errmsg)) if conf.debuglevel > 8: import traceback traceback.print_exc() return [] for _domain in kw['secondary_domains']: user_attrs['domain'] = _domain try: exec("retval = '%s'.%s" % (routine, alternative_mail_routines[number][routine] % user_attrs)) log.debug(_("Appending additional mail address: %s") % (retval), level=8) alternative_mail.append(retval) except KeyError, e: log.warning( _("Attribute substitution for 'alternative_mail' failed in Recipient Policy" )) alternative_mail = utils.normalize(alternative_mail) alternative_mail = list(set(alternative_mail)) return alternative_mail
def handler(*args, **kw): log.info("kolab.handler(args(%d): %r, kw: %r)" % (len(args), args, kw)) auth = Auth() auth.connect() if len(args) == 4: # moddn dn = args[0] new = utils.normalize(args[1]) old = utils.normalize(args[2]) command = args[4] pass elif len(args) == 3: dn = args[0] new = utils.normalize(args[1]) old = utils.normalize(args[2]) if isinstance(old, dict) and len(old.keys()) > 0: # Two options: # - entry changed # - entry deleted log.info("user %r, old is dict" % (dn)) if isinstance(new, dict) and len(new.keys()) > 0: log.info("Modify entry %r" % (dn)) mailserver_attribute = conf.get( 'ldap', 'mailserver_attribute').lower() if mailserver_attribute is None: log.error("Mail server attribute is not set") return if mailserver_attribute in old: log.info( "Modified entry %r has mail server attribute %s: %r" % (dn, mailserver_attribute, new[mailserver_attribute])) if not old[mailserver_attribute] == constants.fqdn: # Even though the new mailserver can be us, it is the # *current* mail server that needs to push for the XFER. log.info( "The mail server for user %r is set, and it is not me (%r)" % (dn, old[mailserver_attribute])) return else: # If old has no mailserver attribute, but new does, we need to create # the user locally. if mailserver_attribute in new: if not new[mailserver_attribute] == constants.fqdn: log.info( "The mail server for user %r is set (in new, not old), but it is not me (%r)" % (dn, new[mailserver_attribute])) return else: log.info( "Entry %r does not have a mail server attribute." % (dn)) return auth._auth._synchronize_callback(change_type='modify', previous_dn=None, change_number=None, dn=dn, entry=new) else: log.info("Delete entry %r" % (dn)) # See if the mailserver_attribute exists mailserver_attribute = conf.get( 'ldap', 'mailserver_attribute').lower() if mailserver_attribute is None: log.error("Mail server attribute is not set") # TODO: Perhaps, query for IMAP servers. If there is only one, # we know what to do. return if mailserver_attribute in old: log.info( "Deleted entry %r has mail server attribute %s: %r" % (dn, mailserver_attribute, old[mailserver_attribute])) if not old[mailserver_attribute] == constants.fqdn: log.info( "The mail server for user %r is set, and it is not me (%r)" % (dn, old[mailserver_attribute])) return else: log.info( "Entry deletion notification for %r does not have a mail server attribute specified." % (dn)) cfg = ConfigRegistry() cfg.load() if cfg.is_true('mail/cyrus/mailbox/delete', True): auth._auth._synchronize_callback(change_type='delete', previous_dn=None, change_number=None, dn=dn, entry=old) elif isinstance(new, dict) and len(new.keys()) > 0: # Old is not a dict (or empty), so the entry is just created log.info("Add entry %r" % (dn)) # See if the mailserver_attribute exists mailserver_attribute = conf.get('ldap', 'mailserver_attribute').lower() if mailserver_attribute is None: log.error("Mail server attribute is not set") # TODO: Perhaps, query for IMAP servers. If there is only one, # we know what to do. return if mailserver_attribute in new: log.info("Added entry %r has mail server attribute %s: %r" % (dn, mailserver_attribute, new[mailserver_attribute])) if not new[mailserver_attribute] == constants.fqdn: log.info( "The mail server for user %r is set, and it is not me (%r)" % (dn, new[mailserver_attribute])) return else: log.info( "Added entry %r does not have a mail server attribute set." % (dn)) return auth._auth._synchronize_callback(change_type='add', previous_dn=None, change_number=None, dn=dn, entry=new) else: log.info("entry %r changed, but no new or old attributes" % (dn))
for routine in alternative_mail_routines[number].keys(): try: exec("retval = '%s'.%s" % (routine,alternative_mail_routines[number][routine] % user_attrs)) log.debug(_("Appending additional mail address: %s") % (retval), level=8) alternative_mail.append(retval) except Exception, errmsg: log.error(_("Policy for secondary email address failed: %r") % (errmsg)) if conf.debuglevel > 8: import traceback traceback.print_exc() return [] for _domain in kw['secondary_domains']: user_attrs['domain'] = _domain try: exec("retval = '%s'.%s" % (routine,alternative_mail_routines[number][routine] % user_attrs)) log.debug(_("Appending additional mail address: %s") % (retval), level=8) alternative_mail.append(retval) except KeyError, e: log.warning(_("Attribute substitution for 'alternative_mail' failed in Recipient Policy")) alternative_mail = utils.normalize(alternative_mail) alternative_mail = list(set(alternative_mail)) return alternative_mail