diff options
| -rw-r--r-- | plugins/sasl_password/README | 65 | ||||
| -rw-r--r-- | plugins/sasl_password/chgsaslpasswd.c | 27 | ||||
| -rw-r--r-- | plugins/sasl_password/locale/de_CH.inc | 16 | ||||
| -rw-r--r-- | plugins/sasl_password/locale/en_US.inc | 16 | ||||
| -rw-r--r-- | plugins/sasl_password/sasl_password.js | 43 | ||||
| -rw-r--r-- | plugins/sasl_password/sasl_password.php | 144 | 
6 files changed, 311 insertions, 0 deletions
| diff --git a/plugins/sasl_password/README b/plugins/sasl_password/README new file mode 100644 index 000000000..3fbc448ff --- /dev/null +++ b/plugins/sasl_password/README @@ -0,0 +1,65 @@ ++-------------------------------------------------------------------------+ +| +|  Author:  Thomas Bruederli +|  Source:  Squirrelmail Change SASL Password Plugin by Galen Johnson +|  Program: sasl_password +|  Version: 1.0 +|  Purpose: Change Cyrus Account Passwords +| ++-------------------------------------------------------------------------+ + + +Purpose +------- +Cyrus SASL database authentication allows your Cyrus+RoundCube +installation to host mail users without requiring a Unix Shell account! + +This plugin only covers the "sasldb" case when using Cyrus SASL. Kerberos +and PAM authentication mechanisms will require other techniques to enable +user password manipulations. + +Cyrus SASL includes a shell utility called "saslpasswd" for manipulating +user passwords in the "sasldb" database.  This patch attempts to use +this utility to perform password manipulations required by your webmail +users without any administrative interaction. Unfortunately, this +scheme requires that the "saslpasswd" utility be run as the "cyrus" +user - kind of a security problem since we have chosen to SUID a small +script which will allow this to happen. + +This plugin is based on the Squirrelmail Change SASL Password Plugin. +See http://www.squirrelmail.org/plugin_view.php?id=107 for details. + + +Installation +------------ +Install just like any other plugin, just put it in the plugin directory +and activate it by adding 'sasl_password' to the list of active plugins +in config/main.inc.php + +Edit the chgsaslpasswd.c and chgsaslpasswd.sh files as is documented +within them. + +Compile the wrapper program: +	gcc -o chgsaslpasswd chgsaslpasswd.c + +Chown the chgsaslpasswd and chgsaslpasswd.sh to the cyrus user and group  +that your browser runs as, then chmod them to 4550. + +For example, if your cyrus user is 'cyrus' and the apache server group is +'nobody' (I've been told Redhat runs Apache as user 'apache'): + +	chown cyrus:nobody chgsaslpasswd +	chmod 4550 chgsaslpasswd + +Stephen Carr has suggested users should try to run the scripts on a test +account as the cyrus user eg; + +	su cyrus -c "./chgsaslpasswd -p test_account" + +This will allow you to make sure that the script will work for your setup. +Should the script not work, make sure that: +1) the user the script runs as has access to the saslpasswd|saslpasswd2 +   file and proper permissions +2) make sure the user in the chgsaslpasswd.c file is set correctly. +   This could save you some headaches if you are the paranoid type. + diff --git a/plugins/sasl_password/chgsaslpasswd.c b/plugins/sasl_password/chgsaslpasswd.c new file mode 100644 index 000000000..17e20c67f --- /dev/null +++ b/plugins/sasl_password/chgsaslpasswd.c @@ -0,0 +1,27 @@ +#include <stdio.h> +#include <unistd.h> + +// set the UID this script will run as (cyrus user) +#define UID 96 +// set the path to saslpasswd or saslpasswd2 +#define CMD "/usr/sbin/saslpasswd2" + +/* INSTALLING: +  gcc -o chgsaslpasswd chgsaslpasswd.c +  chown root.apache chgsaslpasswd +  strip chgsaslpasswd +  chmod 4550 chgsaslpasswd +*/ + +main(int argc, char *argv[]) +{ +  int rc,cc; + +  cc = setuid(UID); +  rc = execvp(CMD, argv); +  if ((rc != 0) || (cc != 0)) +  { +    fprintf(stderr,"__ %s:  failed %d  %d\n",argv[0],rc,cc); +    exit(1); +  } +} diff --git a/plugins/sasl_password/locale/de_CH.inc b/plugins/sasl_password/locale/de_CH.inc new file mode 100644 index 000000000..399efda84 --- /dev/null +++ b/plugins/sasl_password/locale/de_CH.inc @@ -0,0 +1,16 @@ +<?php + +$labels = array(); +$labels['changepasswd']  = 'Passwort ändern'; +$labels['curpasswd']  = 'Aktuelles Passwort'; +$labels['newpasswd']  = 'Neues Passwort'; +$labels['confpasswd']  = 'Passwort Wiederholung'; + +$messages = array(); +$messages['nopassword'] = "Bitte geben Sie ein neues Passwort ein"; +$messages['nocurpassword'] = "Bitte geben Sie Ihr aktuelles Passwort an"; +$messages['passwordincorrect'] = "Das aktuelle Passwort ist nicht korrekt"; +$messages['passwordinconsistency'] = "Das neue Passwort und dessen Wiederholung stimmen nicht überein"; +$messages['successfullysaved'] = "Ihr Passwort wurde erfolgreich geändert"; + +?>
\ No newline at end of file diff --git a/plugins/sasl_password/locale/en_US.inc b/plugins/sasl_password/locale/en_US.inc new file mode 100644 index 000000000..42708b34f --- /dev/null +++ b/plugins/sasl_password/locale/en_US.inc @@ -0,0 +1,16 @@ +<?php + +$labels = array(); +$labels['changepasswd']  = 'Change Password'; +$labels['curpasswd']  = 'Current Password:'; +$labels['newpasswd']  = 'New Password:'; +$labels['confpasswd']  = 'Confirm New Password:'; + +$messages = array(); +$messages['nopassword'] = "Please enter the new password"; +$messages['nocurpassword'] = "Please enter your current password"; +$messages['passwordincorrect'] = "Current password is incorrect"; +$messages['passwordinconsistency'] = "The new password and it's confirmation do not match"; +$messages['successfullysaved'] = "Successfully changed password"; + +?>
\ No newline at end of file diff --git a/plugins/sasl_password/sasl_password.js b/plugins/sasl_password/sasl_password.js new file mode 100644 index 000000000..719dc8268 --- /dev/null +++ b/plugins/sasl_password/sasl_password.js @@ -0,0 +1,43 @@ +/* SASL pssword change interface (tab) */ + +function sasl_password_save() +{ +  var input_curpasswd = $('#saslcurpasswd')[0]; +  var input_newpasswd = $('#saslnewpasswd')[0]; +  var input_confpasswd = $('#saslconfpasswd')[0]; + +  if (input_curpasswd && input_curpasswd.value=='') { +    alert(rcmail.gettext('nocurpassword', 'sasl_password')); +    input_curpasswd.focus(); +  } +  else if (input_newpasswd && input_newpasswd.value=='') { +    alert(rcmail.gettext('nopassword', 'sasl_password')); +    input_newpasswd.focus(); +  } +  else if (input_confpasswd && input_confpasswd.value=='') { +    alert(rcmail.gettext('nopassword', 'sasl_password')); +    input_confpasswd.focus(); +  } +  else if ((input_newpasswd && input_confpasswd) && (input_newpasswd.value != input_confpasswd.value)) { +    alert(rcmail.gettext('passwordinconsistency', 'sasl_password')); +    input_newpasswd.focus(); +  } +  else { +    rcmail.gui_objects.passform.submit(); +  } +} + +if (window.rcmail) { +  rcmail.addEventListener('init', function(evt) { +  // <span id="settingstabdefault" class="tablink"><roundcube:button command="preferences" type="link" label="preferences" title="editpreferences" /></span> +  var tab = $('<span>').attr('id', 'settingstabpluginsaslpassword').addClass('tablink'); +     +  var button = $('<a>').attr('href', rcmail.env.comm_path+'&_action=plugin.saslpassword').html(rcmail.gettext('password')).appendTo(tab); +  button.bind('click', function(e){ return rcmail.command('plugin.saslpassword', this) }); + +  // add button and register commands +  rcmail.add_element(tab, 'tabs'); +  rcmail.register_command('plugin.saslpassword', function() { rcmail.goto_url('plugin.saslpassword') }, true); +  rcmail.register_command('plugin.saslpassword-save', sasl_password_save, true); +  }); +} diff --git a/plugins/sasl_password/sasl_password.php b/plugins/sasl_password/sasl_password.php new file mode 100644 index 000000000..3a23557e9 --- /dev/null +++ b/plugins/sasl_password/sasl_password.php @@ -0,0 +1,144 @@ +<?php + +/** + * Change SASL Password + * + * Plugin that adds functionality ty to change the users Cyrus/SASL password. + * The code is derrived from the Squirrelmail "Change SASL Password" Plugin + * by Galen Johnson. + * + * It only works with saslpasswd2 on the same host where RoundCube runs + * and requires shell access and gcc in order to compile the binary. + * + * For installation instructions please read the README file. + * + * @version 1.0 + * @author Thomas Bruederli + */ +class sasl_password extends rcube_plugin +{ +  public $task = 'settings'; + +  function init() +  { +    $rcmail = rcmail::get_instance(); +    // add Tab label +    $rcmail->output->add_label('password'); +    $this->register_action('plugin.saslpassword', array($this, 'password_init')); +    $this->register_action('plugin.saslpassword-save', array($this, 'password_save')); +    $this->register_handler('plugin.body', array($this, 'password_form')); +    $this->include_script('sasl_password.js'); +  } + +  function password_init() +  { +    $this->add_texts('locale/'); +    $rcmail = rcmail::get_instance(); +    $rcmail->output->set_pagetitle($this->gettext('changepasswd')); +    $rcmail->output->send('plugin'); +  } +   +  function password_save() +  { +    $rcmail = rcmail::get_instance(); + +    $this->add_texts('locale/'); + +    if (!isset($_POST['_curpasswd']) || !isset($_POST['_newpasswd'])) { +      $rcmail->output->command('display_message', $this->gettext('nopassword'), 'error'); +    } +    else { +      $curpwd = get_input_value('_curpasswd', RCUBE_INPUT_POST); +      $newpwd = get_input_value('_newpasswd', RCUBE_INPUT_POST); + +      if ($_SESSION['password'] != $rcmail->encrypt_passwd($curpwd)) { +        $rcmail->output->command('display_message', $this->gettext('passwordincorrect'), 'error'); +      } +      else if ($this->_save($newpwd)) { +        $rcmail->output->command('display_message', $this->gettext('successfullysaved'), 'confirmation'); +        $_SESSION['password'] = $rcmail->encrypt_passwd($newpwd); +      } +      else { +        $rcmail->output->command('display_message', $this->gettext('errorsaving'), 'error'); +      } +    } + +    rcmail_overwrite_action('plugin.saslpassword'); +    rcmail::get_instance()->output->send('plugin'); +  } + +  function password_form() +  { +    $rcmail = rcmail::get_instance(); + +    // add some labels to client +    $rcmail->output->add_label( +        'sasl_password.nopassword', +        'sasl_password.nocurpassword', +        'sasl_password.passwordinconsistency', +        'sasl_password.changepasswd' +    ); + +    $table = new html_table(array('cols' => 2)); + +    // show current password selection +    $field_id = 'saslcurpasswd'; +    $input_newpasswd = new html_passwordfield(array('name' => '_curpasswd', 'id' => $field_id, 'size' => 25)); + +    $table->add('title', html::label($field_id, Q($this->gettext('curpasswd')))); +    $table->add(null, $input_newpasswd->show()); + +    // show new password selection +    $field_id = 'saslnewpasswd'; +    $input_newpasswd = new html_passwordfield(array('name' => '_newpasswd', 'id' => $field_id, 'size' => 25)); + +    $table->add('title', html::label($field_id, Q($this->gettext('newpasswd')))); +    $table->add(null, $input_newpasswd->show()); + +    // show confirm password selection +    $field_id = 'saslconfpasswd'; +    $input_confpasswd = new html_passwordfield(array('name' => '_confpasswd', 'id' => $field_id, 'size' => 25)); + +    $table->add('title', html::label($field_id, Q($this->gettext('confpasswd')))); +    $table->add(null, $input_confpasswd->show()); + +    $out = html::div(array('class' => "settingsbox", 'style' => "margin:0"), +      html::div(array('id' => "userprefs-title"), $this->gettext('changepasswd')) . +      html::div(array('style' => "padding:15px"), $table->show() . +        html::p(null, +          $rcmail->output->button(array( +            'command' => 'plugin.saslpassword-save', +            'type' => 'input', +            'class' => 'button mainaction', +            'label' => 'save' +        ))) +      ) +    ); + +    $rcmail->output->add_gui_object('passform', 'password-form'); + +    return $rcmail->output->form_tag(array( +        'id' => 'password-form', +        'name' => 'password-form', +        'method' => 'post', +        'action' => './?_task=settings&_action=plugin.saslpassword-save', +    ), $out); +  } + +  private function _save($passwd) +  { +    $curdir = realpath(dirname(__FILE__)); +    $username = escapeshellcmd($_SESSION['username']); +    $code = 1; + +    if ($fh = popen("$curdir/chgsaslpasswd -p $username", 'w')) { +      fwrite($fh, $passwd."\n"); +      $code = pclose($fh); +    } + +    return ($code == 0); +  } + +} + +?> | 
