/** * Establish a connection to the LDAP server */ public function connect($host = null) { // Net_LDAP3 does not support IDNA yet // also parse_host() here is very Roundcube specific $host = rcube_utils::idn_to_ascii(rcube_utils::parse_host($host)); return parent::connect($host); }
/** * Handler for submitted form (ajax request) * * Check fields and save to default identity if valid. * Afterwards the session flag is removed and we're done. */ function save_data() { $rcmail = rcmail::get_instance(); $identity = $rcmail->user->get_identity(); $ident_level = intval($rcmail->config->get('identities_level', 0)); $save_data = array('name' => rcube_utils::get_input_value('_name', rcube_utils::INPUT_POST), 'email' => rcube_utils::get_input_value('_email', rcube_utils::INPUT_POST), 'organization' => rcube_utils::get_input_value('_organization', rcube_utils::INPUT_POST), 'signature' => rcube_utils::get_input_value('_signature', rcube_utils::INPUT_POST)); // don't let the user alter the e-mail address if disabled by config if (in_array($ident_level, array(1, 3, 4))) { $save_data['email'] = $identity['email']; } if (empty($save_data['name']) || empty($save_data['email'])) { $rcmail->output->show_message('formincomplete', 'error'); } else { if (!rcube_utils::check_email($save_data['email'] = rcube_utils::idn_to_ascii($save_data['email']))) { $rcmail->output->show_message('emailformaterror', 'error', array('email' => $save_data['email'])); } else { // save data $rcmail->user->update_identity($identity['identity_id'], $save_data); $rcmail->session->remove('plugin.newuserdialog'); // hide dialog $rcmail->output->command('new_user_dialog_close'); $rcmail->output->show_message('successfullysaved', 'confirmation'); } } $rcmail->output->send(); }
function lookup_user_name($args) { if ($this->init_ldap($args['host'])) { $results = $this->ldap->search('*', $args['user'], true); if (count($results->records) == 1) { $user_name = is_array($results->records[0]['name']) ? $results->records[0]['name'][0] : $results->records[0]['name']; $user_email = is_array($results->records[0]['email']) ? $results->records[0]['email'][0] : $results->records[0]['email']; $args['user_name'] = $user_name; $args['email_list'] = array(); if (!$args['user_email'] && strpos($user_email, '@')) { $args['user_email'] = rcube_utils::idn_to_ascii($user_email); } foreach (array_keys($results[0]) as $key) { if (!preg_match('/^email($|:)/', $key)) { continue; } foreach ((array) $results->records[0][$key] as $alias) { if (strpos($alias, '@')) { $args['email_list'][] = rcube_utils::idn_to_ascii($alias); } } } } } return $args; }
public function create_identity($p) { $rcmail = rcmail::get_instance(); // prefs are set in create_user() if ($this->prefs) { if ($this->prefs['full_name']) { $p['record']['name'] = $this->prefs['full_name']; } if (($this->identities_level == 0 || $this->identities_level == 2) && $this->prefs['email_address']) { $p['record']['email'] = $this->prefs['email_address']; } if ($this->prefs['___signature___']) { $p['record']['signature'] = $this->prefs['___signature___']; } if ($this->prefs['reply_to']) { $p['record']['reply-to'] = $this->prefs['reply_to']; } if (($this->identities_level == 0 || $this->identities_level == 1) && isset($this->prefs['identities']) && $this->prefs['identities'] > 1) { for ($i = 1; $i < $this->prefs['identities']; $i++) { unset($ident_data); $ident_data = array('name' => '', 'email' => ''); // required data if ($this->prefs['full_name' . $i]) { $ident_data['name'] = $this->prefs['full_name' . $i]; } if ($this->identities_level == 0 && $this->prefs['email_address' . $i]) { $ident_data['email'] = $this->prefs['email_address' . $i]; } else { $ident_data['email'] = $p['record']['email']; } if ($this->prefs['reply_to' . $i]) { $ident_data['reply-to'] = $this->prefs['reply_to' . $i]; } if ($this->prefs['___sig' . $i . '___']) { $ident_data['signature'] = $this->prefs['___sig' . $i . '___']; } // insert identity $rcmail->user->insert_identity($ident_data); } } // copy address book $contacts = $rcmail->get_address_book(null, true); if ($contacts && count($this->abook)) { foreach ($this->abook as $rec) { // #1487096 handle multi-address and/or too long items $rec['email'] = array_shift(explode(';', $rec['email'])); if (rcube_utils::check_email(rcube_utils::idn_to_ascii($rec['email']))) { $rec['email'] = rcube_utils::idn_to_utf8($rec['email']); $contacts->insert($rec, true); } } } // mark identity as complete for following hooks $p['complete'] = true; } return $p; }
function lookup_user_name($args) { if ($this->init_ldap($args['host'])) { $results = $this->ldap->search('*', $args['user'], true); if (count($results->records) == 1) { $user_name = is_array($results->records[0]['name']) ? $results->records[0]['name'][0] : $results->records[0]['name']; $user_email = is_array($results->records[0]['email']) ? $results->records[0]['email'][0] : $results->records[0]['email']; $args['user_name'] = $user_name; if (!$args['user_email'] && strpos($user_email, '@')) { $args['user_email'] = rcube_utils::idn_to_ascii($user_email); } } } return $args; }
/** * User > Email */ function user2email($p) { $r = $this->findinvirtual('/\\s' . preg_quote($p['user'], '/') . '\\s*$/'); $result = array(); for ($i = 0; $i < count($r); $i++) { $arr = preg_split('/\\s+/', $r[$i]); if (count($arr) > 0 && strpos($arr[0], '@')) { $result[] = rcube_utils::idn_to_ascii(trim(str_replace('\\@', '@', $arr[0]))); if ($p['first']) { $p['email'] = $result[0]; break; } } } $p['email'] = empty($result) ? NULL : $result; return $p; }
/** * User > Email */ function user2email($p) { $dbh = $this->get_dbh(); $sql_result = $dbh->query(preg_replace('/%u/', $dbh->escape($p['user']), $this->config['email'])); while ($sql_arr = $dbh->fetch_array($sql_result)) { if (strpos($sql_arr[0], '@')) { if ($p['extended'] && count($sql_arr) > 1) { $result[] = array('email' => rcube_utils::idn_to_ascii($sql_arr[0]), 'name' => (string) $sql_arr[1], 'organization' => (string) $sql_arr[2], 'reply-to' => (string) rcube_utils::idn_to_ascii($sql_arr[3]), 'bcc' => (string) rcube_utils::idn_to_ascii($sql_arr[4]), 'signature' => (string) $sql_arr[5], 'html_signature' => (int) $sql_arr[6]); } else { $result[] = $sql_arr[0]; } if ($p['first']) { break; } } } $p['email'] = $result; return $p; }
/** * Authenticate hook handler */ function authenticate($args) { if (!empty($_SERVER['REMOTE_USER']) && !empty($_SERVER['KRB5CCNAME'])) { // Load plugin's config file $this->load_config(); $rcmail = rcmail::get_instance(); $host = $rcmail->config->get('krb_authentication_host'); if (is_string($host) && trim($host) !== '' && empty($args['host'])) { $args['host'] = rcube_utils::idn_to_ascii(rcube_utils::parse_host($host)); } if (!empty($_SERVER['REMOTE_USER'])) { $args['user'] = $_SERVER['REMOTE_USER']; $args['pass'] = null; } $args['cookiecheck'] = false; $args['valid'] = true; } return $args; }
function authenticate($args) { // Load plugin's config file $this->load_config(); $host = rcmail::get_instance()->config->get('http_authentication_host'); if (is_string($host) && trim($host) !== '' && empty($args['host'])) { $args['host'] = rcube_utils::idn_to_ascii(rcube_utils::parse_host($host)); } // Allow entering other user data in login form, // e.g. after log out (#1487953) if (!empty($args['user'])) { return $args; } if (!empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER['PHP_AUTH_PW'])) { $args['user'] = $_SERVER['PHP_AUTH_USER']; $args['pass'] = $_SERVER['PHP_AUTH_PW']; } $args['cookiecheck'] = false; $args['valid'] = true; return $args; }
function user2email($params) { $this->log_msg('Search email for user: '******'user']); if ($this->init_ldap()) { foreach ($this->ldap->search('*', $params['user'], 1)->records as $record) { $email = rcube_utils::idn_to_ascii(self::record_attr('email', $record)); $this->log_msg("Found email: {$email}"); if ($params['extended']) { $params['email'][] = array('email' => $email, 'name' => self::record_attr('name', $record), 'organization' => self::record_attr('organization', $record)); } else { $params['email'][] = $email; } if ($params['first']) { break; } } } if (!$params['email']) { $this->log_msg('No email found'); } return $params; }
/** * Return the mail domain configured for the given host * * @param string $host IMAP host * @param boolean $encode If true, domain name will be converted to IDN ASCII * * @return string Resolved SMTP host */ public function mail_domain($host, $encode = true) { $domain = $host; if (is_array($this->prop['mail_domain'])) { if (isset($this->prop['mail_domain'][$host])) { $domain = $this->prop['mail_domain'][$host]; } } else { if (!empty($this->prop['mail_domain'])) { $domain = rcube_utils::parse_host($this->prop['mail_domain']); } } if ($encode) { $domain = rcube_utils::idn_to_ascii($domain); } return $domain; }
/** * Loads configuration, initializes plugin (including sieve connection) */ function start($mode = null) { // register UI objects $this->rc->output->add_handlers(array('filterslist' => array($this, 'filters_list'), 'filtersetslist' => array($this, 'filtersets_list'), 'filterframe' => array($this, 'filter_frame'), 'filterform' => array($this, 'filter_form'), 'filtersetform' => array($this, 'filterset_form'))); // Get connection parameters $host = $this->rc->config->get('managesieve_host', 'localhost'); $port = $this->rc->config->get('managesieve_port'); $tls = $this->rc->config->get('managesieve_usetls', false); $host = rcube_utils::parse_host($host); $host = rcube_utils::idn_to_ascii($host); // remove tls:// prefix, set TLS flag if (($host = preg_replace('|^tls://|i', '', $host, 1, $cnt)) && $cnt) { $tls = true; } if (empty($port)) { $port = getservbyname('sieve', 'tcp'); if (empty($port)) { $port = self::PORT; } } $plugin = $this->rc->plugins->exec_hook('managesieve_connect', array('user' => $_SESSION['username'], 'password' => $this->rc->decrypt($_SESSION['password']), 'host' => $host, 'port' => $port, 'usetls' => $tls, 'auth_type' => $this->rc->config->get('managesieve_auth_type'), 'disabled' => $this->rc->config->get('managesieve_disabled_extensions'), 'debug' => $this->rc->config->get('managesieve_debug', false), 'auth_cid' => $this->rc->config->get('managesieve_auth_cid'), 'auth_pw' => $this->rc->config->get('managesieve_auth_pw'))); // try to connect to managesieve server and to fetch the script $this->sieve = new rcube_sieve($plugin['user'], $plugin['password'], $plugin['host'], $plugin['port'], $plugin['auth_type'], $plugin['usetls'], $plugin['disabled'], $plugin['debug'], $plugin['auth_cid'], $plugin['auth_pw']); if (!($error = $this->sieve->error())) { // Get list of scripts $list = $this->list_scripts(); // reset current script when entering filters UI (#1489412) if ($this->rc->action == 'plugin.managesieve') { $this->rc->session->remove('managesieve_current'); } if ($mode != 'vacation') { if (!empty($_GET['_set']) || !empty($_POST['_set'])) { $script_name = rcube_utils::get_input_value('_set', rcube_utils::INPUT_GPC, true); } else { if (!empty($_SESSION['managesieve_current'])) { $script_name = $_SESSION['managesieve_current']; } } } if ($script_name === null || $script_name === '') { // get (first) active script if (!empty($this->active[0])) { $script_name = $this->active[0]; } else { if ($list) { $script_name = $list[0]; } else { // if script not exists build default script contents $script_file = $this->rc->config->get('managesieve_default'); $script_name = $this->rc->config->get('managesieve_script_name'); if (empty($script_name)) { $script_name = 'roundcube'; } if ($script_file && is_readable($script_file)) { $content = file_get_contents($script_file); } // add script and set it active if ($this->sieve->save_script($script_name, $content)) { $this->activate_script($script_name); $this->list[] = $script_name; } } } } if ($script_name) { $this->sieve->load($script_name); } $error = $this->sieve->error(); } // finally set script objects if ($error) { switch ($error) { case SIEVE_ERROR_CONNECTION: case SIEVE_ERROR_LOGIN: $this->rc->output->show_message('managesieve.filterconnerror', 'error'); rcube::raise_error(array('code' => 403, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__, 'message' => "Unable to connect to managesieve on {$host}:{$port}"), true, false); break; default: $this->rc->output->show_message('managesieve.filterunknownerror', 'error'); break; } // reload interface in case of possible error when specified script wasn't found (#1489412) if ($script_name !== null && !empty($list) && !in_array($script_name, $list)) { $this->rc->output->command('reload', 500); } // to disable 'Add filter' button set env variable $this->rc->output->set_env('filterconnerror', true); $this->script = array(); } else { $this->exts = $this->sieve->get_extensions(); $this->init_script(); $this->rc->output->set_env('currentset', $this->sieve->current); $_SESSION['managesieve_current'] = $this->sieve->current; } return $error; }
/** * Handler for ACL update/create action */ private function action_save() { $mbox = trim(rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GPC, true)); // UTF7-IMAP $user = trim(rcube_utils::get_input_value('_user', rcube_utils::INPUT_GPC)); $acl = trim(rcube_utils::get_input_value('_acl', rcube_utils::INPUT_GPC)); $oldid = trim(rcube_utils::get_input_value('_old', rcube_utils::INPUT_GPC)); $acl = array_intersect(str_split($acl), $this->rights_supported()); $users = $oldid ? array($user) : explode(',', $user); $result = 0; foreach ($users as $user) { $user = trim($user); if (!empty($this->specials) && in_array($user, $this->specials)) { $username = $this->gettext($user); } else { if (!empty($user)) { if (!strpos($user, '@') && ($realm = $this->get_realm())) { $user .= '@' . rcube_utils::idn_to_ascii(preg_replace('/^@/', '', $realm)); } $username = $user; } } if (!$acl || !$user || !strlen($mbox)) { continue; } $user = $this->mod_login($user); $username = $this->mod_login($username); if ($user != $_SESSION['username'] && $username != $_SESSION['username']) { if ($this->rc->storage->set_acl($mbox, $user, $acl)) { $ret = array('id' => rcube_utils::html_identifier($user), 'username' => $username, 'acl' => implode($acl), 'old' => $oldid); $this->rc->output->command('acl_update', $ret); $result++; } } } if ($result) { $this->rc->output->show_message($oldid ? 'acl.updatesuccess' : 'acl.createsuccess', 'confirmation'); } else { $this->rc->output->show_message($oldid ? 'acl.updateerror' : 'acl.createerror', 'error'); } }
/** * Perfom login to the mail server and to the webmail service. * This will also create a new user entry if auto_create_user is configured. * * @param string Mail storage (IMAP) user name * @param string Mail storage (IMAP) password * @param string Mail storage (IMAP) host * * @return boolean True on success, False on failure */ function login($username, $pass, $host = NULL) { if (empty($username)) { return false; } $config = $this->config->all(); if (!$host) { $host = $config['default_host']; } // Validate that selected host is in the list of configured hosts if (is_array($config['default_host'])) { $allowed = false; foreach ($config['default_host'] as $key => $host_allowed) { if (!is_numeric($key)) { $host_allowed = $key; } if ($host == $host_allowed) { $allowed = true; break; } } if (!$allowed) { return false; } } else { if (!empty($config['default_host']) && $host != rcube_utils::parse_host($config['default_host'])) { return false; } } // parse $host URL $a_host = parse_url($host); if ($a_host['host']) { $host = $a_host['host']; $ssl = isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl', 'imaps', 'tls')) ? $a_host['scheme'] : null; if (!empty($a_host['port'])) { $port = $a_host['port']; } else { if ($ssl && $ssl != 'tls' && (!$config['default_port'] || $config['default_port'] == 143)) { $port = 993; } } } if (!$port) { $port = $config['default_port']; } /* Modify username with domain if required Inspired by Marco <P0L0_notspam_binware.org> */ // Check if we need to add domain if (!empty($config['username_domain']) && strpos($username, '@') === false) { if (is_array($config['username_domain']) && isset($config['username_domain'][$host])) { $username .= '@' . rcube_utils::parse_host($config['username_domain'][$host], $host); } else { if (is_string($config['username_domain'])) { $username .= '@' . rcube_utils::parse_host($config['username_domain'], $host); } } } // Convert username to lowercase. If storage backend // is case-insensitive we need to store always the same username (#1487113) if ($config['login_lc']) { $username = mb_strtolower($username); } // try to resolve email address from virtuser table if (strpos($username, '@') && ($virtuser = rcube_user::email2user($username))) { $username = $virtuser; } // Here we need IDNA ASCII // Only rcube_contacts class is using domain names in Unicode $host = rcube_utils::idn_to_ascii($host); if (strpos($username, '@')) { // lowercase domain name list($local, $domain) = explode('@', $username); $username = $local . '@' . mb_strtolower($domain); $username = rcube_utils::idn_to_ascii($username); } // user already registered -> overwrite username if ($user = rcube_user::query($username, $host)) { $username = $user->data['username']; } $storage = $this->get_storage(); // try to log in if (!($login = $storage->connect($host, $username, $pass, $port, $ssl))) { // try with lowercase $username_lc = mb_strtolower($username); if ($username_lc != $username) { // try to find user record again -> overwrite username if (!$user && ($user = rcube_user::query($username_lc, $host))) { $username_lc = $user->data['username']; } if ($login = $storage->connect($host, $username_lc, $pass, $port, $ssl)) { $username = $username_lc; } } } // exit if login failed if (!$login) { return false; } // user already registered -> update user's record if (is_object($user)) { // update last login timestamp $user->touch(); } else { if ($config['auto_create_user']) { if ($created = rcube_user::create($username, $host)) { $user = $created; } else { self::raise_error(array('code' => 620, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__, 'message' => "Failed to create a user record. Maybe aborted by a plugin?"), true, false); } } else { self::raise_error(array('code' => 621, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__, 'message' => "Access denied for new user {$username}. 'auto_create_user' is disabled"), true, false); } } // login succeeded if (is_object($user) && $user->ID) { // Configure environment $this->set_user($user); $this->set_storage_prop(); $this->session_configure(); // fix some old settings according to namespace prefix $this->fix_namespace_settings($user); // create default folders on first login if ($config['create_default_folders'] && (!empty($created) || empty($user->data['last_login']))) { $storage->create_default_folders(); } // set session vars $_SESSION['user_id'] = $user->ID; $_SESSION['username'] = $user->data['username']; $_SESSION['storage_host'] = $host; $_SESSION['storage_port'] = $port; $_SESSION['storage_ssl'] = $ssl; $_SESSION['password'] = $this->encrypt($pass); $_SESSION['login_time'] = time(); if (isset($_REQUEST['_timezone']) && $_REQUEST['_timezone'] != '_default_') { $_SESSION['timezone'] = floatval($_REQUEST['_timezone']); } if (isset($_REQUEST['_dstactive']) && $_REQUEST['_dstactive'] != '_default_') { $_SESSION['dst_active'] = intval($_REQUEST['_dstactive']); } // force reloading complete list of subscribed mailboxes $storage->clear_cache('mailboxes', true); return true; } return false; }
/** * Establish a connection to the LDAP server */ private function _connect() { $rcube = rcube::get_instance(); if (!function_exists('ldap_connect')) { rcube::raise_error(array('code' => 100, 'type' => 'ldap', 'file' => __FILE__, 'line' => __LINE__, 'message' => "No ldap support in this installation of PHP"), true, true); } if (is_resource($this->conn)) { return true; } if (!is_array($this->prop['hosts'])) { $this->prop['hosts'] = array($this->prop['hosts']); } if (empty($this->prop['ldap_version'])) { $this->prop['ldap_version'] = 3; } foreach ($this->prop['hosts'] as $host) { $host = rcube_utils::idn_to_ascii(rcube_utils::parse_host($host)); $hostname = $host . ($this->prop['port'] ? ':' . $this->prop['port'] : ''); $this->_debug("C: Connect [{$hostname}] [{$this->prop['name']}]"); if ($lc = @ldap_connect($host, $this->prop['port'])) { if ($this->prop['use_tls'] === true) { if (!ldap_start_tls($lc)) { continue; } } $this->_debug("S: OK"); ldap_set_option($lc, LDAP_OPT_PROTOCOL_VERSION, $this->prop['ldap_version']); $this->prop['host'] = $host; $this->conn = $lc; if (isset($this->prop['referrals'])) { ldap_set_option($lc, LDAP_OPT_REFERRALS, $this->prop['referrals']); } break; } $this->_debug("S: NOT OK"); } // See if the directory is writeable. if ($this->prop['writable']) { $this->readonly = false; } if (!is_resource($this->conn)) { rcube::raise_error(array('code' => 100, 'type' => 'ldap', 'file' => __FILE__, 'line' => __LINE__, 'message' => "Could not connect to any LDAP server, last tried {$hostname}"), true); return false; } $bind_pass = $this->prop['bind_pass']; $bind_user = $this->prop['bind_user']; $bind_dn = $this->prop['bind_dn']; $this->base_dn = $this->prop['base_dn']; $this->groups_base_dn = $this->prop['groups']['base_dn'] ? $this->prop['groups']['base_dn'] : $this->base_dn; // User specific access, generate the proper values to use. if ($this->prop['user_specific']) { // No password set, use the session password if (empty($bind_pass)) { $bind_pass = $rcube->decrypt($_SESSION['password']); } // Get the pieces needed for variable replacement. if ($fu = $rcube->get_user_name()) { list($u, $d) = explode('@', $fu); } else { $d = $this->mail_domain; } $dc = 'dc=' . strtr($d, array('.' => ',dc=')); // hierarchal domain string $replaces = array('%dn' => '', '%dc' => $dc, '%d' => $d, '%fu' => $fu, '%u' => $u); if ($this->prop['search_base_dn'] && $this->prop['search_filter']) { if (!empty($this->prop['search_bind_dn']) && !empty($this->prop['search_bind_pw'])) { $this->bind($this->prop['search_bind_dn'], $this->prop['search_bind_pw']); } // Search for the dn to use to authenticate $this->prop['search_base_dn'] = strtr($this->prop['search_base_dn'], $replaces); $this->prop['search_filter'] = strtr($this->prop['search_filter'], $replaces); $this->_debug("S: searching with base {$this->prop['search_base_dn']} for {$this->prop['search_filter']}"); $res = @ldap_search($this->conn, $this->prop['search_base_dn'], $this->prop['search_filter'], array('uid')); if ($res) { if (($entry = ldap_first_entry($this->conn, $res)) && ($bind_dn = ldap_get_dn($this->conn, $entry))) { $this->_debug("S: search returned dn: {$bind_dn}"); $dn = ldap_explode_dn($bind_dn, 1); $replaces['%dn'] = $dn[0]; } } else { $this->_debug("S: " . ldap_error($this->conn)); } // DN not found if (empty($replaces['%dn'])) { if (!empty($this->prop['search_dn_default'])) { $replaces['%dn'] = $this->prop['search_dn_default']; } else { rcube::raise_error(array('code' => 100, 'type' => 'ldap', 'file' => __FILE__, 'line' => __LINE__, 'message' => "DN not found using LDAP search."), true); return false; } } } // Replace the bind_dn and base_dn variables. $bind_dn = strtr($bind_dn, $replaces); $this->base_dn = strtr($this->base_dn, $replaces); $this->groups_base_dn = strtr($this->groups_base_dn, $replaces); if (empty($bind_user)) { $bind_user = $u; } } if (empty($bind_pass)) { $this->ready = true; } else { if (!empty($bind_dn)) { $this->ready = $this->bind($bind_dn, $bind_pass); } else { if (!empty($this->prop['auth_cid'])) { $this->ready = $this->sasl_bind($this->prop['auth_cid'], $bind_pass, $bind_user); } else { $this->ready = $this->sasl_bind($bind_user, $bind_pass); } } } return $this->ready; }
function save($curpass, $passwd) { $rcmail = rcmail::get_instance(); if (!($sql = $rcmail->config->get('password_query'))) { $sql = 'SELECT update_passwd(%c, %u)'; } if ($dsn = $rcmail->config->get('password_db_dsn')) { $db = rcube_db::factory($dsn, '', false); $db->set_debug((bool) $rcmail->config->get('sql_debug')); } else { $db = $rcmail->get_dbh(); } if ($db->is_error()) { return PASSWORD_ERROR; } // new password - default hash method if (strpos($sql, '%P') !== false) { $password = password::hash_password($passwd); if ($password === false) { return PASSWORD_CRYPT_ERROR; } $sql = str_replace('%P', $db->quote($password), $sql); } // old password - default hash method if (strpos($sql, '%O') !== false) { $password = password::hash_password($curpass); if ($password === false) { return PASSWORD_CRYPT_ERROR; } $sql = str_replace('%O', $db->quote($password), $sql); } // crypted password (deprecated, use %P) if (strpos($sql, '%c') !== false) { $password = password::hash_password($passwd, 'crypt', false); if ($password === false) { return PASSWORD_CRYPT_ERROR; } $sql = str_replace('%c', $db->quote($password), $sql); } // dovecotpw (deprecated, use %P) if (strpos($sql, '%D') !== false) { $password = password::hash_password($passwd, 'dovecot', false); if ($password === false) { return PASSWORD_CRYPT_ERROR; } $sql = str_replace('%D', $db->quote($password), $sql); } // hashed passwords (deprecated, use %P) if (strpos($sql, '%n') !== false) { $password = password::hash_password($passwd, 'hash', false); if ($password === false) { return PASSWORD_CRYPT_ERROR; } $sql = str_replace('%n', $db->quote($password, 'text'), $sql); } // hashed passwords (deprecated, use %P) if (strpos($sql, '%q') !== false) { $password = password::hash_password($curpass, 'hash', false); if ($password === false) { return PASSWORD_CRYPT_ERROR; } $sql = str_replace('%q', $db->quote($password, 'text'), $sql); } // Handle clear text passwords securely (#1487034) $sql_vars = array(); if (preg_match_all('/%[p|o]/', $sql, $m)) { foreach ($m[0] as $var) { if ($var == '%p') { $sql = preg_replace('/%p/', '?', $sql, 1); $sql_vars[] = (string) $passwd; } else { // %o $sql = preg_replace('/%o/', '?', $sql, 1); $sql_vars[] = (string) $curpass; } } } $local_part = $rcmail->user->get_username('local'); $domain_part = $rcmail->user->get_username('domain'); $username = $_SESSION['username']; $host = $_SESSION['imap_host']; // convert domains to/from punnycode if ($rcmail->config->get('password_idn_ascii')) { $domain_part = rcube_utils::idn_to_ascii($domain_part); $username = rcube_utils::idn_to_ascii($username); $host = rcube_utils::idn_to_ascii($host); } else { $domain_part = rcube_utils::idn_to_utf8($domain_part); $username = rcube_utils::idn_to_utf8($username); $host = rcube_utils::idn_to_utf8($host); } // at least we should always have the local part $sql = str_replace('%l', $db->quote($local_part, 'text'), $sql); $sql = str_replace('%d', $db->quote($domain_part, 'text'), $sql); $sql = str_replace('%u', $db->quote($username, 'text'), $sql); $sql = str_replace('%h', $db->quote($host, 'text'), $sql); $res = $db->query($sql, $sql_vars); if (!$db->is_error()) { if (strtolower(substr(trim($sql), 0, 6)) == 'select') { if ($db->fetch_array($res)) { return PASSWORD_SUCCESS; } } else { // This is the good case: 1 row updated if ($db->affected_rows($res) == 1) { return PASSWORD_SUCCESS; } // @TODO: Some queries don't affect any rows // Should we assume a success if there was no error? } } return PASSWORD_ERROR; }
protected function _startup() { $rcmail = rcube::get_instance(); if (!$this->sieve) { // Add include path for internal classes $include_path = $this->home . '/lib' . PATH_SEPARATOR; $include_path .= ini_get('include_path'); set_include_path($include_path); // try to connect to managesieve server and to fetch the script $this->sieve = new rcube_sieve($_SESSION['username'], $rcmail->decrypt($_SESSION['password']), rcube_utils::idn_to_ascii(rcube_utils::parse_host($rcmail->config->get('sieverules_host'))), $rcmail->config->get('sieverules_port'), $rcmail->config->get('sieverules_auth_type', NULL), $rcmail->config->get('sieverules_usetls'), $this->current_ruleset, $this->home, $rcmail->config->get('sieverules_use_elsif', true), $rcmail->config->get('sieverules_auth_cid', NULL), $rcmail->config->get('sieverules_auth_pw', NULL), $rcmail->config->get('sieverules_conn_options', NULL)); if ($rcmail->config->get('sieverules_debug', false)) { $this->sieve->set_debug(true); } $this->sieve_error = $this->sieve->error(); if ($this->sieve_error == SIEVE_ERROR_NOT_EXISTS) { // load default rule set if ($this->_get_rule_file($rcmail->config->get('sieverules_default_file')) || sizeof($this->sieve->list) > 0) { $rcmail->overwrite_action('plugin.sieverules.setup'); $this->action = 'plugin.sieverules.setup'; } // that's not exactly an error $this->sieve_error = false; } elseif ($this->sieve_error) { switch ($this->sieve_error) { case SIEVE_ERROR_CONNECTION: case SIEVE_ERROR_LOGIN: $this->api->output->command('display_message', $this->gettext('filterconnerror'), 'error'); break; default: $this->api->output->command('display_message', $this->gettext('filterunknownerror'), 'error'); break; } $this->api->output->set_env('sieveruleserror', true); } // finally set script objects if ($this->sieve_error) { $this->script = array(); } else { $this->script = $this->sieve->script->as_array(); // load example filters $this->examples = $this->_get_rule_file($rcmail->config->get('sieverules_example_file'), true); } } else { $this->sieve->set_ruleset($this->current_ruleset); $this->script = $this->sieve->script->as_array(); } }
function rcube_idn_to_ascii($str) { _deprecation_warning(__FUNCTION__); return rcube_utils::idn_to_ascii($str); }
/** * Establish a connection to the LDAP server */ public function connect($host = null) { if (!function_exists('ldap_connect')) { rcube::raise_error(array('code' => 100, 'type' => 'ldap', 'file' => __FILE__, 'line' => __LINE__, 'message' => "No ldap support in this installation of PHP"), true); return false; } if (is_resource($this->conn) && $this->config['host'] == $host) { return true; } if (empty($this->config['ldap_version'])) { $this->config['ldap_version'] = 3; } // iterate over hosts if none specified if (!$host) { if (!is_array($this->config['hosts'])) { $this->config['hosts'] = array($this->config['hosts']); } foreach ($this->config['hosts'] as $host) { if ($this->connect($host)) { return true; } } return false; } // open connection to the given $host $host = rcube_utils::idn_to_ascii(rcube_utils::parse_host($host)); $hostname = $host . ($this->config['port'] ? ':' . $this->config['port'] : ''); $this->_debug("C: Connect to {$hostname} [{$this->config['name']}]"); if ($lc = @ldap_connect($host, $this->config['port'])) { if ($this->config['use_tls'] === true) { if (!ldap_start_tls($lc)) { return false; } } $this->_debug("S: OK"); ldap_set_option($lc, LDAP_OPT_PROTOCOL_VERSION, $this->config['ldap_version']); $this->config['host'] = $host; $this->conn = $lc; if (!empty($this->config['network_timeout'])) { ldap_set_option($lc, LDAP_OPT_NETWORK_TIMEOUT, $this->config['network_timeout']); } if (isset($this->config['referrals'])) { ldap_set_option($lc, LDAP_OPT_REFERRALS, $this->config['referrals']); } if (isset($this->config['dereference'])) { ldap_set_option($lc, LDAP_OPT_DEREF, $this->config['dereference']); } } else { $this->_debug("S: NOT OK"); } if (!is_resource($this->conn)) { rcube::raise_error(array('code' => 100, 'type' => 'ldap', 'file' => __FILE__, 'line' => __LINE__, 'message' => "Could not connect to any LDAP server, last tried {$hostname}"), true); return false; } return true; }
function rcube_idn_to_ascii($str) { return rcube_utils::idn_to_ascii($str); }
private function _startup() { $rcmail = rcube::get_instance(); if (!$this->sieve) { include 'lib/Net/Sieve.php'; include 'include/rcube_sieve.php'; include 'include/rcube_sieve_script.php'; $rcmail = rcube::get_instance(); // try to connect to managesieve server and to fetch the script $this->sieve = new rcube_sieve($_SESSION['username'], $rcmail->decrypt($_SESSION['password']), rcube_utils::idn_to_ascii(rcube_utils::parse_host($rcmail->config->get('sieverules_host'))), $rcmail->config->get('sieverules_port'), $rcmail->config->get('sieverules_auth_type', NULL), $rcmail->config->get('sieverules_usetls'), $this->current_ruleset, $this->home, $rcmail->config->get('sieverules_use_elsif', true), $rcmail->config->get('sieverules_auth_cid', NULL), $rcmail->config->get('sieverules_auth_pw', NULL)); if ($rcmail->config->get('sieverules_debug', false)) { $this->sieve->set_debug(true); } $this->sieve_error = $this->sieve->error(); if ($this->sieve_error == SIEVE_ERROR_NOT_EXISTS) { // load default rule set if ($rcmail->config->get('sieverules_default_file', false) && is_readable($rcmail->config->get('sieverules_default_file')) || sizeof($this->sieve->list) > 0) { $rcmail->overwrite_action('plugin.sieverules.setup'); $this->action = 'plugin.sieverules.setup'; } elseif ($rcmail->config->get('sieverules_default_file', false) && !is_readable($rcmail->config->get('sieverules_default_file'))) { rcube::raise_error(array('code' => 600, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__, 'message' => "SieveRules plugin: Unable to open default rule file"), true, false); } // that's not exactly an error $this->sieve_error = false; } elseif ($this->sieve_error) { switch ($this->sieve_error) { case SIEVE_ERROR_CONNECTION: case SIEVE_ERROR_LOGIN: $this->api->output->command('display_message', $this->gettext('filterconnerror'), 'error'); break; default: $this->api->output->command('display_message', $this->gettext('filterunknownerror'), 'error'); break; } $this->api->output->set_env('sieveruleserror', true); } // finally set script objects if ($this->sieve_error) { $this->script = array(); } else { $this->script = $this->sieve->script->as_array(); // load example filters if ($rcmail->config->get('sieverules_example_file', false) && is_readable($rcmail->config->get('sieverules_example_file'))) { $this->examples = $this->sieve->script->parse_text(file_get_contents($rcmail->config->get('sieverules_example_file'))); } elseif ($rcmail->config->get('sieverules_example_file', false) && !is_readable($rcmail->config->get('sieverules_example_file'))) { rcube::raise_error(array('code' => 600, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__, 'message' => "SieveRules plugin: Unable to open example rule file"), true, false); } } } else { $this->sieve->set_ruleset($this->current_ruleset); $this->script = $this->sieve->script->as_array(); } }
/** * Perfom login to the mail server and to the webmail service. * This will also create a new user entry if auto_create_user is configured. * * @param string Mail storage (IMAP) user name * @param string Mail storage (IMAP) password * @param string Mail storage (IMAP) host * @param bool Enables cookie check * * @return boolean True on success, False on failure */ function login($username, $pass, $host = null, $cookiecheck = false) { $this->login_error = null; if (empty($username)) { return false; } if ($cookiecheck && empty($_COOKIE)) { $this->login_error = self::ERROR_COOKIES_DISABLED; return false; } $default_host = $this->config->get('default_host'); $default_port = $this->config->get('default_port'); $username_domain = $this->config->get('username_domain'); $login_lc = $this->config->get('login_lc', 2); // host is validated in rcmail::autoselect_host(), so here // we'll only handle unset host (if possible) if (!$host && !empty($default_host)) { if (is_array($default_host)) { list($key, $val) = each($default_host); $host = is_numeric($key) ? $val : $key; } else { $host = $default_host; } $host = rcube_utils::parse_host($host); } if (!$host) { $this->login_error = self::ERROR_INVALID_HOST; return false; } // parse $host URL $a_host = parse_url($host); if ($a_host['host']) { $host = $a_host['host']; $ssl = isset($a_host['scheme']) && in_array($a_host['scheme'], array('ssl', 'imaps', 'tls')) ? $a_host['scheme'] : null; if (!empty($a_host['port'])) { $port = $a_host['port']; } else { if ($ssl && $ssl != 'tls' && (!$default_port || $default_port == 143)) { $port = 993; } } } if (!$port) { $port = $default_port; } // Check if we need to add/force domain to username if (!empty($username_domain)) { $domain = is_array($username_domain) ? $username_domain[$host] : $username_domain; if ($domain = rcube_utils::parse_host((string) $domain, $host)) { $pos = strpos($username, '@'); // force configured domains if ($pos !== false && $this->config->get('username_domain_forced')) { $username = substr($username, 0, $pos) . '@' . $domain; } else { if ($pos === false) { $username .= '@' . $domain; } } } } // Convert username to lowercase. If storage backend // is case-insensitive we need to store always the same username (#1487113) if ($login_lc) { if ($login_lc == 2 || $login_lc === true) { $username = mb_strtolower($username); } else { if (strpos($username, '@')) { // lowercase domain name list($local, $domain) = explode('@', $username); $username = $local . '@' . mb_strtolower($domain); } } } // try to resolve email address from virtuser table if (strpos($username, '@') && ($virtuser = rcube_user::email2user($username))) { $username = $virtuser; } // Here we need IDNA ASCII // Only rcube_contacts class is using domain names in Unicode $host = rcube_utils::idn_to_ascii($host); $username = rcube_utils::idn_to_ascii($username); // user already registered -> overwrite username if ($user = rcube_user::query($username, $host)) { $username = $user->data['username']; } $storage = $this->get_storage(); // try to log in if (!$storage->connect($host, $username, $pass, $port, $ssl)) { return false; } // user already registered -> update user's record if (is_object($user)) { // update last login timestamp $user->touch(); } else { if ($this->config->get('auto_create_user')) { if ($created = rcube_user::create($username, $host)) { $user = $created; } else { self::raise_error(array('code' => 620, 'file' => __FILE__, 'line' => __LINE__, 'message' => "Failed to create a user record. Maybe aborted by a plugin?"), true, false); } } else { self::raise_error(array('code' => 621, 'file' => __FILE__, 'line' => __LINE__, 'message' => "Access denied for new user {$username}. 'auto_create_user' is disabled"), true, false); } } // login succeeded if (is_object($user) && $user->ID) { // Configure environment $this->set_user($user); $this->set_storage_prop(); // set session vars $_SESSION['user_id'] = $user->ID; $_SESSION['username'] = $user->data['username']; $_SESSION['storage_host'] = $host; $_SESSION['storage_port'] = $port; $_SESSION['storage_ssl'] = $ssl; $_SESSION['password'] = $this->encrypt($pass); $_SESSION['login_time'] = time(); if (isset($_REQUEST['_timezone']) && $_REQUEST['_timezone'] != '_default_') { $_SESSION['timezone'] = rcube_utils::get_input_value('_timezone', rcube_utils::INPUT_GPC); } // fix some old settings according to namespace prefix $this->fix_namespace_settings($user); // set/create special folders $this->set_special_folders(); // clear all mailboxes related cache(s) $storage->clear_cache('mailboxes', true); return true; } return false; }
public function create_identity($p) { $rcmail = rcmail::get_instance(); // prefs are set in create_user() if ($this->prefs) { if ($this->prefs['full_name']) { $p['record']['name'] = $this->prefs['full_name']; } if (($this->identities_level == 0 || $this->identities_level == 2) && $this->prefs['email_address']) { $p['record']['email'] = $this->prefs['email_address']; } if ($this->prefs['___signature___']) { $p['record']['signature'] = $this->prefs['___signature___']; } if ($this->prefs['reply_to']) { $p['record']['reply-to'] = $this->prefs['reply_to']; } if (($this->identities_level == 0 || $this->identities_level == 1) && isset($this->prefs['identities']) && $this->prefs['identities'] > 1) { for ($i = 1; $i < $this->prefs['identities']; $i++) { unset($ident_data); $ident_data = array('name' => '', 'email' => ''); // required data if ($this->prefs['full_name' . $i]) { $ident_data['name'] = $this->prefs['full_name' . $i]; } if ($this->identities_level == 0 && $this->prefs['email_address' . $i]) { $ident_data['email'] = $this->prefs['email_address' . $i]; } else { $ident_data['email'] = $p['record']['email']; } if ($this->prefs['reply_to' . $i]) { $ident_data['reply-to'] = $this->prefs['reply_to' . $i]; } if ($this->prefs['___sig' . $i . '___']) { $ident_data['signature'] = $this->prefs['___sig' . $i . '___']; } // insert identity $rcmail->user->insert_identity($ident_data); } } // copy address book $contacts = $rcmail->get_address_book(null, true); $addresses = array(); $groups = array(); if ($contacts && !empty($this->abook)) { foreach ($this->abook as $rec) { // #1487096: handle multi-address and/or too long items // #1487858: convert multi-address contacts into groups $emails = preg_split('/[;,]/', $rec['email'], -1, PREG_SPLIT_NO_EMPTY); $group_id = null; // create group for addresses if (count($emails) > 1) { if (!($group_id = $groups[$rec['name']])) { if ($group = $contacts->create_group($rec['name'])) { $group_id = $group['id']; $groups[$rec['name']] = $group_id; } } } // create contacts foreach ($emails as $email) { if (!($contact_id = $addresses[$email]) && rcube_utils::check_email(rcube_utils::idn_to_ascii($email))) { $rec['email'] = rcube_utils::idn_to_utf8($email); if ($contact_id = $contacts->insert($rec, true)) { $addresses[$email] = $contact_id; } } if ($group_id && $contact_id) { $contacts->add_to_group($group_id, array($contact_id)); } } } } // mark identity as complete for following hooks $p['complete'] = true; } return $p; }
/** * Check the given data before saving. * If input isn't valid, the message to display can be fetched using get_error() * * @param array Assoziative array with data to save * @param boolean Attempt to fix/complete record automatically * @return boolean True if input is valid, False if not. */ public function validate(&$save_data, $autofix = false) { $rcube = rcube::get_instance(); $valid = true; // check validity of email addresses foreach ($this->get_col_values('email', $save_data, true) as $email) { if (strlen($email)) { if (!rcube_utils::check_email(rcube_utils::idn_to_ascii($email))) { $error = $rcube->gettext(array('name' => 'emailformaterror', 'vars' => array('email' => $email))); $this->set_error(self::ERROR_VALIDATE, $error); $valid = false; break; } } } // allow plugins to do contact validation and auto-fixing $plugin = $rcube->plugins->exec_hook('contact_validate', array('record' => $save_data, 'autofix' => $autofix, 'valid' => $valid)); if ($valid && !$plugin['valid']) { $this->set_error(self::ERROR_VALIDATE, $plugin['error']); } if (is_array($plugin['record'])) { $save_data = $plugin['record']; } return $plugin['valid']; }
/** * SMTP Connection and authentication * * @param string Server host * @param string Server port * @param string User name * @param string Password * * @return bool Returns true on success, or false on error */ public function connect($host = null, $port = null, $user = null, $pass = null) { $rcube = rcube::get_instance(); // disconnect/destroy $this->conn $this->disconnect(); // reset error/response var $this->error = $this->response = null; // let plugins alter smtp connection config $CONFIG = $rcube->plugins->exec_hook('smtp_connect', array('smtp_server' => $host ? $host : $rcube->config->get('smtp_server'), 'smtp_port' => $port ? $port : $rcube->config->get('smtp_port', 25), 'smtp_user' => $user ? $user : $rcube->config->get('smtp_user'), 'smtp_pass' => $pass ? $pass : $rcube->config->get('smtp_pass'), 'smtp_auth_cid' => $rcube->config->get('smtp_auth_cid'), 'smtp_auth_pw' => $rcube->config->get('smtp_auth_pw'), 'smtp_auth_type' => $rcube->config->get('smtp_auth_type'), 'smtp_helo_host' => $rcube->config->get('smtp_helo_host'), 'smtp_timeout' => $rcube->config->get('smtp_timeout'), 'smtp_auth_callbacks' => array())); $smtp_host = rcube_utils::parse_host($CONFIG['smtp_server']); // when called from Installer it's possible to have empty $smtp_host here if (!$smtp_host) { $smtp_host = 'localhost'; } $smtp_port = is_numeric($CONFIG['smtp_port']) ? $CONFIG['smtp_port'] : 25; $smtp_host_url = parse_url($smtp_host); // overwrite port if (isset($smtp_host_url['host']) && isset($smtp_host_url['port'])) { $smtp_host = $smtp_host_url['host']; $smtp_port = $smtp_host_url['port']; } // re-write smtp host if (isset($smtp_host_url['host']) && isset($smtp_host_url['scheme'])) { $smtp_host = sprintf('%s://%s', $smtp_host_url['scheme'], $smtp_host_url['host']); } // remove TLS prefix and set flag for use in Net_SMTP::auth() if (preg_match('#^tls://#i', $smtp_host)) { $smtp_host = preg_replace('#^tls://#i', '', $smtp_host); $use_tls = true; } if (!empty($CONFIG['smtp_helo_host'])) { $helo_host = $CONFIG['smtp_helo_host']; } else { if (!empty($_SERVER['SERVER_NAME'])) { $helo_host = preg_replace('/:\\d+$/', '', $_SERVER['SERVER_NAME']); } else { $helo_host = 'localhost'; } } // IDNA Support $smtp_host = rcube_utils::idn_to_ascii($smtp_host); $this->conn = new Net_SMTP($smtp_host, $smtp_port, $helo_host); if ($rcube->config->get('smtp_debug')) { $this->conn->setDebug(true, array($this, 'debug_handler')); } // register authentication methods if (!empty($CONFIG['smtp_auth_callbacks']) && method_exists($this->conn, 'setAuthMethod')) { foreach ($CONFIG['smtp_auth_callbacks'] as $callback) { $this->conn->setAuthMethod($callback['name'], $callback['function'], isset($callback['prepend']) ? $callback['prepend'] : true); } } // try to connect to server and exit on failure $result = $this->conn->connect($smtp_timeout); if (PEAR::isError($result)) { $this->response[] = "Connection failed: " . $result->getMessage(); $this->error = array('label' => 'smtpconnerror', 'vars' => array('code' => $this->conn->_code)); $this->conn = null; return false; } // workaround for timeout bug in Net_SMTP 1.5.[0-1] (#1487843) if (method_exists($this->conn, 'setTimeout') && ($timeout = ini_get('default_socket_timeout'))) { $this->conn->setTimeout($timeout); } $smtp_user = str_replace('%u', $_SESSION['username'], $CONFIG['smtp_user']); $smtp_pass = str_replace('%p', $rcube->decrypt($_SESSION['password']), $CONFIG['smtp_pass']); $smtp_auth_type = empty($CONFIG['smtp_auth_type']) ? NULL : $CONFIG['smtp_auth_type']; if (!empty($CONFIG['smtp_auth_cid'])) { $smtp_authz = $smtp_user; $smtp_user = $CONFIG['smtp_auth_cid']; $smtp_pass = $CONFIG['smtp_auth_pw']; } // attempt to authenticate to the SMTP server if ($smtp_user && $smtp_pass) { // IDNA Support if (strpos($smtp_user, '@')) { $smtp_user = rcube_utils::idn_to_ascii($smtp_user); } $result = $this->conn->auth($smtp_user, $smtp_pass, $smtp_auth_type, $use_tls, $smtp_authz); if (PEAR::isError($result)) { $this->error = array('label' => 'smtpautherror', 'vars' => array('code' => $this->conn->_code)); $this->response[] .= 'Authentication failure: ' . $result->getMessage() . ' (Code: ' . $result->getCode() . ')'; $this->reset(); $this->disconnect(); return false; } } return true; }
/** * Check the given data before saving. * If input isn't valid, the message to display can be fetched using get_error() * * @param array Assoziative array with data to save * @param boolean Attempt to fix/complete record automatically * @return boolean True if input is valid, False if not. */ public function validate(&$save_data, $autofix = false) { $rcmail = rcmail::get_instance(); // check validity of email addresses foreach ($this->get_col_values('email', $save_data, true) as $email) { if (strlen($email)) { if (!rcube_utils::check_email(rcube_utils::idn_to_ascii($email))) { $error = $rcmail->gettext(array('name' => 'emailformaterror', 'vars' => array('email' => $email))); $this->set_error(self::ERROR_VALIDATE, $error); return false; } } } return true; }
/** * Helper function to build a Mail_mime object to send an iTip message * * @param array Event object to send * @param string iTip method (REQUEST|REPLY|CANCEL) * @param boolean Request RSVP * @return object Mail_mime object with message data */ public function compose_itip_message($event, $method, $rsvp = true) { $from = rcube_utils::idn_to_ascii($this->sender['email']); $from_utf = rcube_utils::idn_to_utf8($from); $sender = format_email_recipient($from, $this->sender['name']); // truncate list attendees down to the recipient of the iTip Reply. // constraints for a METHOD:REPLY according to RFC 5546 if ($method == 'REPLY') { $replying_attendee = null; $reply_attendees = array(); foreach ($event['attendees'] as $attendee) { if ($attendee['role'] == 'ORGANIZER') { $reply_attendees[] = $attendee; } else { if (strcasecmp($attendee['email'], $from) == 0 || strcasecmp($attendee['email'], $from_utf) == 0) { $replying_attendee = $attendee; if ($attendee['status'] != 'DELEGATED') { unset($replying_attendee['rsvp']); // unset the RSVP attribute } } else { if (!empty($attendee['delegated-to']) && (strcasecmp($attendee['delegated-to'], $from) == 0 || strcasecmp($attendee['delegated-to'], $from_utf) == 0) || !empty($attendee['delegated-from']) && (strcasecmp($attendee['delegated-from'], $from) == 0 || strcasecmp($attendee['delegated-from'], $from_utf) == 0)) { $reply_attendees[] = $attendee; } } } } if ($replying_attendee) { array_unshift($reply_attendees, $replying_attendee); $event['attendees'] = $reply_attendees; } if ($event['recurrence']) { unset($event['recurrence']['EXCEPTIONS']); } } else { if ($method == 'REQUEST') { foreach ($event['attendees'] as $i => $attendee) { if (($rsvp || !isset($attendee['rsvp'])) && ($attendee['status'] != 'DELEGATED' && $attendee['role'] != 'NON-PARTICIPANT')) { $event['attendees'][$i]['rsvp'] = (bool) $rsvp; } } } else { if ($method == 'CANCEL') { if ($event['recurrence']) { unset($event['recurrence']['EXCEPTIONS']); } } } } // compose multipart message using PEAR:Mail_Mime $message = new Mail_mime("\r\n"); $message->setParam('text_encoding', 'quoted-printable'); $message->setParam('head_encoding', 'quoted-printable'); $message->setParam('head_charset', RCUBE_CHARSET); $message->setParam('text_charset', RCUBE_CHARSET . ";\r\n format=flowed"); $message->setContentType('multipart/alternative'); // compose common headers array $headers = array('From' => $sender, 'Date' => $this->rc->user_date(), 'Message-ID' => $this->rc->gen_message_id(), 'X-Sender' => $from); if ($agent = $this->rc->config->get('useragent')) { $headers['User-Agent'] = $agent; } $message->headers($headers); // attach ics file for this event $ical = libcalendaring::get_ical(); $ics = $ical->export(array($event), $method, false, $method == 'REQUEST' && $this->plugin->driver ? array($this->plugin->driver, 'get_attachment_body') : false); $filename = $event['_type'] == 'task' ? 'todo.ics' : 'event.ics'; $message->addAttachment($ics, 'text/calendar', $filename, false, '8bit', '', RCUBE_CHARSET . "; method=" . $method); return $message; }
function save($curpass, $passwd) { $rcmail = rcmail::get_instance(); if (!($sql = $rcmail->config->get('password_query'))) { $sql = 'SELECT update_passwd(%c, %u)'; } if ($dsn = $rcmail->config->get('password_db_dsn')) { // #1486067: enable new_link option if (is_array($dsn) && empty($dsn['new_link'])) { $dsn['new_link'] = true; } else { if (!is_array($dsn) && !preg_match('/\\?new_link=true/', $dsn)) { $dsn .= '?new_link=true'; } } $db = rcube_db::factory($dsn, '', false); $db->set_debug((bool) $rcmail->config->get('sql_debug')); $db->db_connect('w'); } else { $db = $rcmail->get_dbh(); } if ($db->is_error()) { return PASSWORD_ERROR; } // crypted password if (strpos($sql, '%c') !== FALSE) { $salt = ''; if (!($crypt_hash = $rcmail->config->get('password_crypt_hash'))) { if (CRYPT_MD5) { $crypt_hash = 'md5'; } else { if (CRYPT_STD_DES) { $crypt_hash = 'des'; } } } switch ($crypt_hash) { case 'md5': $len = 8; $salt_hashindicator = '$1$'; break; case 'des': $len = 2; break; case 'blowfish': $cost = (int) $rcmail->config->get('password_blowfish_cost'); $cost = $cost < 4 || $cost > 31 ? 12 : $cost; $len = 22; $salt_hashindicator = sprintf('$2a$%02d$', $cost); break; case 'sha256': $len = 16; $salt_hashindicator = '$5$'; break; case 'sha512': $len = 16; $salt_hashindicator = '$6$'; break; default: return PASSWORD_CRYPT_ERROR; } //Restrict the character set used as salt (#1488136) $seedchars = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; for ($i = 0; $i < $len; $i++) { $salt .= $seedchars[rand(0, 63)]; } $sql = str_replace('%c', $db->quote(crypt($passwd, $salt_hashindicator ? $salt_hashindicator . $salt . '$' : $salt)), $sql); } // dovecotpw if (strpos($sql, '%D') !== FALSE) { if (!($dovecotpw = $rcmail->config->get('password_dovecotpw'))) { $dovecotpw = 'dovecotpw'; } if (!($method = $rcmail->config->get('password_dovecotpw_method'))) { $method = 'CRAM-MD5'; } // use common temp dir $tmp_dir = $rcmail->config->get('temp_dir'); $tmpfile = tempnam($tmp_dir, 'roundcube-'); $pipe = popen("{$dovecotpw} -s '{$method}' > '{$tmpfile}'", "w"); if (!$pipe) { unlink($tmpfile); return PASSWORD_CRYPT_ERROR; } else { fwrite($pipe, $passwd . "\n", 1 + strlen($passwd)); usleep(1000); fwrite($pipe, $passwd . "\n", 1 + strlen($passwd)); pclose($pipe); $newpass = trim(file_get_contents($tmpfile), "\n"); if (!preg_match('/^\\{' . $method . '\\}/', $newpass)) { return PASSWORD_CRYPT_ERROR; } if (!$rcmail->config->get('password_dovecotpw_with_method')) { $newpass = trim(str_replace('{' . $method . '}', '', $newpass)); } unlink($tmpfile); } $sql = str_replace('%D', $db->quote($newpass), $sql); } // hashed passwords if (preg_match('/%[n|q]/', $sql)) { if (!extension_loaded('hash')) { rcube::raise_error(array('code' => 600, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__, 'message' => "Password plugin: 'hash' extension not loaded!"), true, false); return PASSWORD_ERROR; } if (!($hash_algo = strtolower($rcmail->config->get('password_hash_algorithm')))) { $hash_algo = 'sha1'; } $hash_passwd = hash($hash_algo, $passwd); $hash_curpass = hash($hash_algo, $curpass); if ($rcmail->config->get('password_hash_base64')) { $hash_passwd = base64_encode(pack('H*', $hash_passwd)); $hash_curpass = base64_encode(pack('H*', $hash_curpass)); } $sql = str_replace('%n', $db->quote($hash_passwd, 'text'), $sql); $sql = str_replace('%q', $db->quote($hash_curpass, 'text'), $sql); } // Handle clear text passwords securely (#1487034) $sql_vars = array(); if (preg_match_all('/%[p|o]/', $sql, $m)) { foreach ($m[0] as $var) { if ($var == '%p') { $sql = preg_replace('/%p/', '?', $sql, 1); $sql_vars[] = (string) $passwd; } else { // %o $sql = preg_replace('/%o/', '?', $sql, 1); $sql_vars[] = (string) $curpass; } } } $local_part = $rcmail->user->get_username('local'); $domain_part = $rcmail->user->get_username('domain'); $username = $_SESSION['username']; $host = $_SESSION['imap_host']; // convert domains to/from punnycode if ($rcmail->config->get('password_idn_ascii')) { $domain_part = rcube_utils::idn_to_ascii($domain_part); $username = rcube_utils::idn_to_ascii($username); $host = rcube_utils::idn_to_ascii($host); } else { $domain_part = rcube_utils::idn_to_utf8($domain_part); $username = rcube_utils::idn_to_utf8($username); $host = rcube_utils::idn_to_utf8($host); } // at least we should always have the local part $sql = str_replace('%l', $db->quote($local_part, 'text'), $sql); $sql = str_replace('%d', $db->quote($domain_part, 'text'), $sql); $sql = str_replace('%u', $db->quote($username, 'text'), $sql); $sql = str_replace('%h', $db->quote($host, 'text'), $sql); $res = $db->query($sql, $sql_vars); if (!$db->is_error()) { if (strtolower(substr(trim($sql), 0, 6)) == 'select') { if ($db->fetch_array($res)) { return PASSWORD_SUCCESS; } } else { // This is the good case: 1 row updated if ($db->affected_rows($res) == 1) { return PASSWORD_SUCCESS; } // @TODO: Some queries don't affect any rows // Should we assume a success if there was no error? } } return PASSWORD_ERROR; }
/** * Connect to configured managesieve server * * @param string $username User login * @param string $password User password * * @return int Connection status: 0 on success, >0 on failure */ public function connect($username, $password) { // Get connection parameters $host = $this->rc->config->get('managesieve_host', 'localhost'); $port = $this->rc->config->get('managesieve_port'); $tls = $this->rc->config->get('managesieve_usetls', false); $host = rcube_utils::parse_host($host); $host = rcube_utils::idn_to_ascii($host); // remove tls:// prefix, set TLS flag if (($host = preg_replace('|^tls://|i', '', $host, 1, $cnt)) && $cnt) { $tls = true; } if (empty($port)) { $port = getservbyname('sieve', 'tcp'); if (empty($port)) { $port = self::PORT; } } $plugin = $this->rc->plugins->exec_hook('managesieve_connect', array('user' => $username, 'password' => $password, 'host' => $host, 'port' => $port, 'usetls' => $tls, 'auth_type' => $this->rc->config->get('managesieve_auth_type'), 'disabled' => $this->rc->config->get('managesieve_disabled_extensions'), 'debug' => $this->rc->config->get('managesieve_debug', false), 'auth_cid' => $this->rc->config->get('managesieve_auth_cid'), 'auth_pw' => $this->rc->config->get('managesieve_auth_pw'), 'socket_options' => $this->rc->config->get('managesieve_conn_options'))); // try to connect to managesieve server and to fetch the script $this->sieve = new rcube_sieve($plugin['user'], $plugin['password'], $plugin['host'], $plugin['port'], $plugin['auth_type'], $plugin['usetls'], $plugin['disabled'], $plugin['debug'], $plugin['auth_cid'], $plugin['auth_pw'], $plugin['socket_options']); $error = $this->sieve->error(); if ($error) { rcube::raise_error(array('code' => 403, 'file' => __FILE__, 'line' => __LINE__, 'message' => "Unable to connect to managesieve on {$host}:{$port}"), true, false); } return $error; }