Re: sam + ldap patch
Neil Sequeira <[email protected]> Thu, 18 Sep 2003 14:24:12 -0400
| Newsgroups | gmane.comp.horde.sam |
|---|---|
| Organization | NCS Consulting Inc. |
| Message-ID | <[email protected]> |
Jan Schneider wrote: > Zitat von Neil Sequeira <[email protected]>: > >> Here's a start at an LDAP backend for sam. It needs the > > Great! But please try to follow the coding standards. > > Jan. > An updated patch is attached. It should follow the coding conventions and it fixes a bug displaying the blacklist. BTW, this patch does a horrible job of handling errors (it silently ignores them!) because i'm not familiar with Horde (PEAR?) error reporting functions yet. I hope to have it updated with better error reporting down the road (time permitting). -neil -- sam mailing list Frequently Asked Questions: http://horde.org/faq/ To unsubscribe, mail: [email protected]
sam.ldap.newpatch
(text/x-diff, 9.5 KB)
diff -ru -N sam/config/backends.php.dist sam.new/config/backends.php.dist
--- sam/config/backends.php.dist 2003-09-06 13:53:24.000000000 -0400
+++ sam.new/config/backends.php.dist 2003-09-17 22:37:48.000000000 -0400
@@ -121,3 +121,49 @@
),
),
);
+
+/* SpamAssassin LDAP storage example. */
+$backends['spamd_ldap'] = array(
+ 'preferred' => '',
+ 'hordeauth' => true,
+ 'driver' => 'spamd_ldap',
+ 'params' => array(
+ 'ldapserver' => 'localhost',
+ 'basedn' => 'ou=users,dc=example,dc=com',
+ 'attribute' => 'spamassassinConfig',
+ 'uid' => 'uid',
+ 'option_map' => array(
+ 'hit_level' => 'required_hits',
+ 'subject_tag' => 'subject_tag',
+ 'rewrite_sub' => 'rewrite_subject',
+ 'level_stars' => 'spam_level_stars',
+ 'report_header' => 'report_header',
+ 'terse_report' => 'use_terse_report',
+ 'defang_mime' => 'defang_mime',
+ 'skip_rbl' => 'skip_rbl_checks',
+ ),
+ 'defaults' => array(
+ 'hit_level' => '5',
+ 'subject_tag' => '***SPAM***',
+ 'rewrite_sub' => 1,
+ 'level_stars' => 1,
+ 'report_header' => 0,
+ 'terse_report' => 1,
+ 'defang_mime' => 1,
+ 'skip_rbl' => 1,
+ ),
+ 'capabilities' => array(
+ 'hit_level',
+ 'report_header',
+ 'rewrite_sub',
+ 'subject_tag',
+ 'level_stars',
+ 'defang_mime',
+ 'whitelist_to',
+ 'whitelist_from',
+ 'blacklist_to',
+ 'blacklist_from',
+ 'skip_rbl'
+ ),
+ ),
+);
diff -ru -N sam/lib/Driver/spamd_ldap.php sam.new/lib/Driver/spamd_ldap.php
--- sam/lib/Driver/spamd_ldap.php 1969-12-31 19:00:00.000000000 -0500
+++ sam.new/lib/Driver/spamd_ldap.php 2003-09-18 14:09:43.000000000 -0400
@@ -0,0 +1,246 @@
+<?php
+/**
+ * $Horde: sam/lib/Driver/spamd_ldap.php,v 1.32 2003/09/18 17:32:44 max Exp $
+ * SAM storage implementation for LDAP backend - based on spamd_sql.php.
+ * Requires SpamAssassin patch found at:
+ * http://bugzilla.spamassassin.org/show_bug.cgi?id=2205
+ *
+ * Required parameters:
+ * ====================
+ * 'ldapserver' -- The hostname of the ldap server.
+ * 'basedn' -- The password associated with 'username'.
+ * 'attribute' -- The database type (ie. 'pgsql', 'mysql, etc.).
+ * 'uid' -- The communication protocol ('tcp', 'unix', etc.).
+ *
+ * @author Chris Bowlby <[email protected]>
+ * @author Max Kalika <[email protected]>
+ * @author Neil Sequeira <[email protected]>
+ * @version $Revision: 1.32 $
+ * @since SAM 0.0.1
+ * @package sam
+ */
+
+class SAM_Driver_spamd_ldap extends SAM_Driver {
+
+ /**
+ * Handle for the current LDAP connection.
+ *
+ * @var $_linkid
+ */
+ var $_linkid;
+
+ /**
+ * Boolean indicating whether or not we're connected to the LDAP server.
+ *
+ * @var boolean $_connected
+ */
+ var $_connected = false;
+
+ /**
+ * List of the capabilities supported by this driver.
+ * This has been moved into the backend configuration
+ * to make disabling capabilities easier.
+ *
+ * @var array $_capabilities
+ */
+/*
+ var $_capabilities = array('hit_level',
+ 'report_header',
+ 'rewrite_sub',
+ 'subject_tag',
+ 'level_stars',
+ 'defang_mime',
+ 'whitelist_to',
+ 'whitelist_from',
+ 'blacklist_to',
+ 'blacklist_from',
+ 'skip_rbl');
+*/
+ /**
+ * Constructs a new LDAP storage object.
+ *
+ * @access public
+ *
+ * @param string $user The user who owns these SPAM options.
+ * @param optional array $params A hash containing connection
+ * parameters.
+ */
+ function SAM_Driver_spamd_ldap($user, $params = array())
+ {
+ $this->_user = $user;
+ $this->_params = $params;
+ $this->_capabilities = $params['capabilities'];
+ }
+
+ /**
+ * Converts a SAM attribute to an option that SpamAssassin will use.
+ *
+ * @access private
+ *
+ * @param string $attribute The SAM attribute to convert.
+ *
+ * @return string The converted SpamAssassin option or the original
+ * attribute if no match is found.
+ */
+ function _mapAttributeToOption($attribute)
+ {
+ return isset($this->_params['option_map'][$attribute])
+ ? $this->_params['option_map'][$attribute] : $attribute;
+ }
+
+ /**
+ * Converts a SpamAssassin option to a SAM attribute.
+ *
+ * @access private
+ *
+ * @param string $option The SpamAssassin option to convert.
+ *
+ * @return string The converted SAM attribute or the original option if
+ * no match is found.
+ */
+ function _mapOptionToAttribute($option)
+ {
+ $attribute_map = array();
+ if (isset($this->_params['option_map'])) {
+ $attribute_map = array_flip($this->_params['option_map']);
+ }
+
+ return isset($attribute_map[$option])
+ ? $attribute_map[$option] : $option;
+ }
+
+ /**
+ * Retrieve an option set from the storage backend.
+ *
+ * @access private
+ *
+ */
+ function retrieve()
+ {
+ /* Make sure we have a valid database connection. */
+ $this->_connect();
+ /* set default values */
+ $this->_setDefaults();
+ $eres = false;
+ $user = $this->_user;
+ $attrib = strtolower($this->_params['attribute']);
+ $filter = "(".$this->_params['uid']."=$user)";
+ $res = ldap_search($this->_linkid, $this->_params['basedn'],
+ $filter, array($attrib));
+ if ($res) $eres = ldap_get_entries($this->_linkid, $res);
+ if ($eres && isset($eres[0][$attrib])) {
+ for ($i = 0; $i < $eres[0][$attrib]['count']; $i++) {
+ list($a,$v) = explode(" ", $eres[0][$attrib][$i]);
+ $ra = $this->_mapOptionToAttribute($a);
+ if (is_numeric($v)) {
+ if (ereg('\.',$v)) {
+ $newoptions[$ra][] = (float) $v;
+ } else {
+ $newoptions[$ra][] = (int) $v;
+ }
+ }
+ else {
+ $newoptions[$ra][] = $v;
+ }
+ }
+ /* go through new options and pull single values */
+ /* out of their arrays */
+ foreach($newoptions as $k => $v) {
+ if (count($v) > 1) {
+ $this->_options[$k] = $v;
+ }
+ else {
+ $this->_options[$k] = $v[0];
+ }
+ }
+ }
+ }
+
+ /**
+ * Set default values
+ *
+ * @access private
+ *
+ */
+ function _setDefaults()
+ {
+ $defaults = $this->_params['defaults'];
+ foreach($defaults as $a => $v) {
+ $this->_options[$a] = $v;
+ }
+ }
+
+ /**
+ * Store an option set in the storage backend.
+ *
+ * @access private
+ *
+ * @return boolean True on success or false on failure.
+ */
+ function store()
+ {
+ /* Make sure we have a valid database connection. */
+ if (!$this->_connect()) { return false; }
+ $user = $this->_user;
+ $attrib = $this->_params['attribute'];
+ $userdn = $this->_params['uid']."=$user,".$this->_params['basedn'];
+ $store = $this->_options;
+ foreach($store as $a => $v) {
+ $sa = $this->_mapAttributeToOption($a);
+ if (is_array($v)) {
+ foreach($v as $av)
+ $entry[$attrib][] = "$sa $av";
+ } else {
+ $entry[$attrib][] = "$sa $v";
+ }
+ }
+ return (ldap_modify($this->_linkid, $userdn, $entry));
+ }
+
+ /**
+ * Attempts to open a connection to the LDAP server.
+ *
+ * @access private
+ *
+ * @return boolean True on success or false on failure.
+ */
+ function _connect()
+ {
+ if ($this->_connected) return true;
+ $bindpass = Auth::getCredential('password');
+ $user = $this->_user;
+ $binddn = $this->_params['uid']."=$user,".$this->_params['basedn'];
+ Horde::assertDriverConfig($this->_params, 'spamd_ldap',
+ array('ldapserver', 'basedn', 'attribute', 'uid'),
+ 'SAM backend', 'backends.php', '$backends');
+ for ($tries = 3; $tries > 0; $tries--) { /* try three times */
+ $lc = ldap_connect($this->_params['ldapserver']);
+ if ($lc) {
+ $lb = ldap_bind($lc, $binddn, $bindpass);
+ if ($lb) {
+ $this->_linkid = $lc;
+ $this->connected = true;
+ return true;
+ } else {
+ ldap_unbind($lc);
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Disconnect from the LDAP server and clean up the connection.
+ *
+ * @return boolean True on success, false on failure.
+ */
+ function _disconnect()
+ {
+ if ($this->_connected) {
+ $this->_connected = false;
+ return ldap_unbind($this->_linkid);
+ }
+ return true;
+ }
+
+}