# jabber und ispconfig



## FlobbyDisk (3. Nov. 2011)

Hi,

gibts irgendwelche pläne einen jabberserver "offiziel" in ispconfig zu unterstützen??

oder hat es jemand geschafft die mail_user tabelle als authentifizierungsquelle für einen jabberserver zu verwenden??

hab bisher ejabberd in verwendung, allerdings standalone... wäre schön wenn jeder mailuser automatisch auch gleich einen jabberaccount hätte.... 

mFg
FlO


----------



## nghgn (9. Feb. 2012)

Hast du das mittlerweile hinbekommen?

Stehe nun vor dem selben Problem.


----------



## FlobbyDisk (11. Feb. 2012)

Hi,

leider nicht, hatte folgende links als "grundlage" herangezogen, aber mit meinen php/mysql kentnissen bin ich gescheitert...


ejabberd an syscp:
eJabberd an Syscp Mail-Benutzer authentifizieren | rxtx-server.de

das wäre genau das was ich mit ispconfig gerne hätte.....

oder allgemein ejabberd an mysql:
Authenticate ejabberd with an mysql database | Sebastian Mogilowskis Blog


mFg
FlO


----------



## Horfic (11. Feb. 2012)

Ich würde es ned über mysql machen, da hätte erstens der mysql wieder zu viel rechte für die ispconfig db und falls ispconfig mal was ändert geht wieder nix.

Nimm bei ejabbered external authenticaten und schreib halt ein perl oder php script welches sich auf den remote user verbindet.

Wennst php nimmst, dann nimm die nusoap lib weil die persistent soap verbindungen erlaubt.

Gibt im prinzip eh nur 3 funktionen zum implementieren, isuser, auth und setpass.

Wenn man auch sich regestrieren soll über das external script dann kommt eben noch was dazu.

Ist doch easy^^


----------



## nghgn (11. Feb. 2012)

Servus,

das Auth-Skript an sich ist ja nicht das Problem. Da gibt es zig Beispiele.

Mein Problem ist, dass ich mit dem verschlüsselten Kennwort mit Salt nicht ganz klar komme. Ich steig da nicht ganz durch.

Eigentlich reicht mir ein Code Schnipsel, der es mir erlaubt die beiden Kennwörter miteinander zu vergleichen. 

Falls du zufällig einen parat hast immer her damit.

Den Rest gibts ja schon.

Gruß

NgHgN


----------



## Horfic (11. Feb. 2012)

Ja ispconfig benutzt einfach crypt mit salt. 

Hier die crypt funktion von ispconfig


```
public function crypt_password($cleartext_password) {
        $salt="$1$";
        $base64_alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
        for ($n=0;$n<8;$n++) {
            $salt.=$base64_alphabet[mt_rand(0,63)];
        }
        $salt.="$";
        return crypt($cleartext_password,$salt);
    }
```
und hier noch zum vergleichen



```
if (crypt($benutzer_eingabe, $passwort) == $passwort) {
   echo "Passwort stimmt überein!";
}
```


----------



## Horfic (13. Feb. 2012)

Falls du es noch immer nicht hast, hier. Habs mal schnell geschrieben, aber nicht getestet.


```
#!/usr/bin/php
<?php

error_reporting(0);
$auth = new JabberAuth();
$auth->dbhost = "";
$auth->dbuser = "";
$auth->dbpass = "";
$auth->dbbase = "";
$auth->allow_setpass = true;
$auth->play(); // We simply start process !

class JabberAuth {
    var $dbhost; /* MySQL server */
    var $dbuser; /* MySQL user */
    var $dbpass; /* MySQL password */
    var $dbbase; /* MySQL database where users are stored */
  var $allow_setpass; /*Allow that the user can change the password*/

    var $debug         = false;                       /* Debug mode */
    var $debugfile     = "/var/log/pipe-debug.log";  /* Debug output */
    var $logging     = false;                       /* Do we log requests ? */
    var $logfile     = "/var/log/pipe-log.log" ;   /* Log file ... */
    /*
     * For both debug and logging, ejabberd have to be able to write.
     */
    
    var $jabber_user;   /* This is the jabber user passed to the script. filled by $this->command() */
    var $jabber_pass;   /* This is the jabber user password passed to the script. filled by $this->command() */
    var $jabber_server; /* This is the jabber server passed to the script. filled by $this->command(). Useful for VirtualHosts */
    var $jid;           /* Simply the JID, if you need it, you have to fill. */
    var $data;          /* This is what SM component send to us. */
    
    var $dateformat = "M d H:i:s"; /* Check date() for string format. */
    var $command; /* This is the command sent ... */
    var $mysock;  /* MySQL connection ressource */
    var $stdin;   /* stdin file pointer */
    var $stdout;  /* stdout file pointer */

    function JabberAuth()
    {
        @define_syslog_variables();
        @openlog("pipe-auth", LOG_NDELAY, LOG_SYSLOG);
        
        if($this->debug) {
            @error_reporting(E_ALL);
            @ini_set("log_errors", "1");
            @ini_set("error_log", $this->debugfile);
        }
        $this->logg("Starting pipe-auth ..."); // We notice that it's starting ...
        $this->openstd();
    }
    
    function stop()
    {
        $this->logg("Shutting down ..."); // Sorry, have to go ...
        closelog();
        $this->closestd(); // Simply close files
        exit(0); // and exit cleanly
    }
    
    function openstd()
    {
        $this->stdout = @fopen("php://stdout", "w"); // We open STDOUT so we can read
        $this->stdin  = @fopen("php://stdin", "r"); // and STDIN so we can talk !
    }
    
    function readstdin()
    {
        $l      = @fgets($this->stdin, 3); // We take the length of string
        $length = @unpack("n", $l); // ejabberd give us something to play with ...
        $len    = $length["1"]; // and we now know how long to read.
        if($len > 0) { // if not, we'll fill logfile ... and disk full is just funny once
            $this->logg("Reading $len bytes ... "); // We notice ...
            $data   = @fgets($this->stdin, $len+1);
            // $data = iconv("UTF-8", "ISO-8859-15", $data); // To be tested, not sure if still needed.
            $this->data = $data; // We set what we got.
            $this->logg("IN: ".$data);
        }
    }
    
    function closestd()
    {
        @fclose($this->stdin); // We close everything ...
        @fclose($this->stdout);
    }
    
    function out($message)
    {
        @fwrite($this->stdout, $message); // We reply ...
        $dump = @unpack("nn", $message);
        $dump = $dump["n"];
        $this->logg("OUT: ". $dump);
    }
    
    function myalive()
    {
        if(!is_resource($this->mysock) || !@mysql_ping($this->mysock)) { // check if we have a MySQL connection and if it's valid.
            $this->mysql(); // We try to reconnect if MySQL gone away ...
            return @mysql_ping($this->mysock); // we simply try again, to be sure ...
        } else {
            return true; // so good !
        }
    }
  
  function gen_pass($cleartext_password)
  {
    $salt="$1$";
    $base64_alphabet='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    
    for ($n=0;$n<8;$n++)
    {
      $salt.=$base64_alphabet[mt_rand(0,63)];
    }
    
    $salt.="$";
    
    return crypt($cleartext_password,$salt);
  }
    
    function play()
    {
        do {
            $this->readstdin(); // get data
            $length = strlen($this->data); // compute data length
            if($length > 0 ) { // for debug mainly ...
                $this->logg("GO: ".$this->data);
                $this->logg("data length is : ".$length);
            }
            $ret = $this->command(); // play with data !
            $this->logg("RE: " . $ret); // this is what WE send.
            $this->out($ret); // send what we reply.
            $this->data = NULL; // more clean. ...
        } while (true);
    }
    
    function command()
    {
        $data = $this->splitcomm(); // This is an array, where each node is part of what SM sent to us :
        // 0 => the command,
        // and the others are arguments .. e.g. : user, server, password ...
        
        if($this->myalive()) { // Check we can play with MySQL
            if(strlen($data[0]) > 0 ) {
                $this->logg("Command was : ".$data[0]);
            }
            switch($data[0]) {
                case "isuser": // this is the "isuser" command, used to check for user existance
                        $this->jabber_user = $data[1];
                        $parms = $data[1];  // only for logging purpose
                        $return = $this->checkuser();
                    break;
                    
                case "auth": // check login, password
                        $this->jabber_user = $data[1];
                        $this->jabber_pass = $data[3];
                        $parms = $data[1].":".$data[2].":".md5($data[3]); // only for logging purpose
                        $return = $this->checkpass();
                    break;
                    
                case "setpass":
            if ($this->allow_setpass === true) {
              $return = $this->setpass();
            } else {
              $return = false; // We do not want jabber to be able to change password
            }
                    break;
                    
                default:
                        $this->stop(); // if it's not something known, we have to leave.
                        // never had a problem with this using ejabberd, but might lead to problem ?
                    break;
            }
            
            $return = ($return) ? 1 : 0;
            
            if(strlen($data[0]) > 0 && strlen($parms) > 0) {
                $this->logg("Command : ".$data[0].":".$parms." ==> ".$return." ");
            }
            return @pack("nn", 2, $return);
        } else {
            // $this->prevenir(); // Maybe useful to tell somewhere there's a problem ...
            return @pack("nn", 2, 0); // it's so bad.
        }
    }
    
  function setpass()
    {
    $password = $this->gen_pass($this->jabber_pass);
        $result = mysql_query("UPDATE `mail_user` 
      SET `password` = '".$password."' 
      WHERE `login` = '".$this->jabber_user."'", $this->mysock);

    if (mysql_affected_rows() != 0) {
      return true;
    } else {
      return false;
    }
    }
  
    function checkpass()
    {
        $result = mysql_query("SELECT password 
      FROM `mail_user` 
      WHERE `login` = '".$this->jabber_user."' LIMIT 1"
      , $this->mysock);
    $password = mysql_result($result, 0);

    if (crypt($this->jabber_pass, $password) == $password) {
      return true;
    } else {
      return false;
    }
    }
    
    function checkuser()
    {
        $result = mysql_query("SELECT mailuser_id 
      FROM `mail_user` 
      WHERE `login` = '".$this->jabber_user."' LIMIT 1"
      , $this->mysock);
      
        if(mysql_num_rows($result) != 0) {
            return true;
        } else {
            return false;
        }
    }
    
    function splitcomm() // simply split command and arugments into an array.
    {
        return explode(":", $this->data);
    }
    
    function mysql() // "MySQL abstraction", this opens a permanent MySQL connection, and fill the ressource
    {
        $this->mysock = @mysql_pconnect($this->dbhost, $this->dbuser, $this->dbpass);
        @mysql_select_db($this->dbbase, $this->mysock);
        $this->logg("MySQL :: ". (is_resource($this->mysock) ? "Connected"));
    }
    
    function logg($message) // pretty simple, using syslog.
    // some says it doesn't work ? perhaps, but AFAIR, it was working.
    {
        if($this->logging) {
            @syslog(LOG_INFO, $message);
        }
    }
}
?>
```


----------



## nowayback (13. Feb. 2012)

Zitat von Horfic:


> Falls du es noch immer nicht hast, hier. Habs mal schnell geschrieben, aber nicht getestet.


So so...

http://www.ejabberd.im/files/efiles/check_mysql.php.txt


Nix dagegen wenn du helfen willst, aber geistiges Eigentum anderer als dein Eigenes zu verkaufen ist dreist!

Grüße
nwb


----------



## Horfic (13. Feb. 2012)

Ich brauchs eh ned, hab ned mal ejabber, außerdem ist es mir so egal. 

Nehmt es oder schmeißt es weg.

PS: Von lizenzen halt ich sowieso nix

PPS: Und wenn wir schon so sind, müsste mich jeder der mein Mailuser interface für Roundcube benutzt mich anschreiben ob er es benutzen darf, weil es unter copyright (ohne lizenz) ist.


----------



## nghgn (13. Feb. 2012)

Ball flach halten, Jung!!!

@Horfic: erstmal Danke fürs Umschreiben, hatte bisher noch keine Zeit dazu. Werde es heute Abend testen.

@nowayback: Es gibt wohl keinen Menschen auf der Welt, der eigentlich nicht schon halb im Knast steht.


----------



## nghgn (13. Feb. 2012)

Läuft nicht,

aber das hier läuft:

```
#!/usr/bin/perl

# Mysql external auth script
# Features: auth isUser and change password
# Password is an encrypted password !!

# 2009-02-04 - by Mogilowski Sebastian - http://www.mogilowski.net

# Settings
my $sDatabaseHost='localhost';            # The hostname of the database server
my $sDatabaseUser="ispconfig";            # The username to connect to mysql
my $sDatabasePass='';            # The password to connect to mysql
my $sDatabaseName="dbispconfig";            # The name of the database contain the user table
my $sUserTable="mail_user";                # The name of the table containing the username and password
my $sUsernameTableField="email";        # The name of the field that holds jabber user names
my $sPasswordTableField="password";    # The name of the field that holds jabber passwords

# Libs
use DBI;
use DBD::mysql;

while(1) {
my $sBuffer = "";
my $readBuffer = sysread STDIN,$sBuffer,2;
my $iBufferLength = unpack "n",$sBuffer;
my $readBuffer    = sysread STDIN,$sBuffer,$iBufferLength;
my ($sOperation,$sUsername,$sDomain,$sPassword) = split /:/,$sBuffer;
$sUsername = $sUsername . "@" . $sDomain;
my $bResult;

SWITCH: {
$sOperation eq 'auth' and do {
$bResult   = 0;
$connect   = DBI->connect('DBI:mysql:'.$sDatabaseName, $sDatabaseUser, $sDatabasePass) || die "Could not connect to database: $DBI::errstr";
$query     = "SELECT $sPasswordTableField FROM $sUserTable WHERE $sUsernameTableField='$sUsername';";
$statement = $connect->prepare($query);
$statement->execute();
while ($row = $statement->fetchrow_hashref()) {
$sCryptstring = crypt($sPassword,$row->{$sPasswordTableField});
if ($row->{$sPasswordTableField} eq $sCryptstring) {
$bResult = 1;
}
}
},last SWITCH;

$sOperation eq 'setpass' and do {
$bResult = 0;
},last SWITCH;

$sOperation eq 'isuser' and do {
$bResult   = 0;
$connect   = DBI->connect('DBI:mysql:'.$sDatabaseName, $sDatabaseUser, $sDatabasePass) || die "Could not connect to database: $DBI::errstr";
$myquery   = "SELECT count(*) AS iCount FROM $sUserTable WHERE $sUsernameTableField='$sUsername';";
$statement = $connect->prepare($myquery);
$statement->execute();
$row = $statement->fetchrow_hashref();
if($row->{'iCount'} >= 1){
$bResult = 1;
}
},last SWITCH;
};

my $sOutput = pack "nn",2,$bResult ? 1 : 0;
syswrite STDOUT,$sOutput;
}
closelog;
```
Der Fehler lag ganz woanders. Und zwar muss man die Jabber-Domains nochmal extra in der ejabberd.cfg wie folgt angeben:

```
%% Hostname
{hosts, ["localhost","domain1.de","domain2.de"]}.
```
Den Teil zur Passwortänderung habe ich entfernt. Brauche ich nicht und würde sowieso nicht funktionieren.

Trotzdem danke für deine Hilfe.


----------



## Horfic (13. Feb. 2012)

warum würds ned funzen?

die passwörter werden richtig erzeugt und in die db eingetrage.

Der mailserver liest die passwörter direkt aus der db


----------



## nghgn (13. Feb. 2012)

Das kann ich dir leider auch nicht sagen.

Zumindest meldet mein Client Kennwort falsch und das Log zeigt am Server nur an, dass eine Verbindung aufgebaut wurde. Beim Perl Skript gibts noch eine weitere Zeile, dass das Kennwort akzeptiert wurde.


----------



## herosalex (10. Okt. 2012)

Könnte mir einer Helfen irgendwie funktioniert das nicht.
Habe die Dateien erstellt und umgeändert.
Leider werden keine Mail-User von Jabber übernommen.


----------

