Andreas Korthaus: Probleme mit POST Header (multipart/form-data)

Hallo!

Ich habe mal versucht selbst einen POST Header zu schreiben, mit dem  ich später einmal einen gz-komprimierten String übertragen will. Aber es funkioniert noch nichtmal mit einem "normalen" String. Mein Script:

<?php

$host = "www.server.de";
 $path = "/test.php";
 $boundary ="-----------------------------305242850528394";

$name = "da_name";
 $filename = "da_filename";
 $gzstring = "HIER_SOLL_MAL_EIN_GZ-STRING_HIN";

$data = $boundary."\n";
 $data .= "Content-Disposition: form-data; ";
 $data .= "name="$name"; ";
 $data .= "filename="$filename"\n";
 $data .= "Content-Type:text/plain\n\n";
 $data .= $gzstring."\n";

$header = "POST $path HTTP/1.1\n";
    $header .= "Host: $host\n";
 $header .= "Content-length: ".strlen($data)."\n";
    $header .= "Content-type: multipart/form-data; boundary=$boundary\n\n";
 $header .= $data;
 $header .= $boundary."--\n";

$fp = fsockopen($host, 80);
    fputs($fp, $header);

while(!feof($fp)) {
        $res .= fread($fp,1);
    }
    fclose($fp);

echo $res;
?>

Das Script test.php enthält folgenden Code:

<?php
echo "<pre>";
print_r($GLOBALS);
echo "</pre>";
?>

Aber was ich zurückbekomme ist irgendwie "kaputt":

erst normal:
HTTP/1.1 200 OK Date: Sun, 29 Sep 2002 00:09:44
...

es fängt korrekt die Ausgabe von $GLOBALS an, dann auf einmal:

[GATEWAY_INTERFACE] => CGI/1.1
    [SERVER_PROTOCOL] => HTTP/1.1

1

1

1
[
e
REQUEST_METHOD
5
] =>
4
POST
1

1

1

1

1

1
[
c
QUERY_STRING
5
] =>
1

1

1

1

1

1
[
b
REQUEST_URI
5
] =>
d

usw, bis zum Ende, und dann kommt

Method Not Implemented
-----------------------------305242850528394-- to / not supported.

Invalid method in request -----------------------------305242850528394--

Als Vorlage für den Request dienten mir zum einen mein eigener "Mitschnitt"(</?m=136310&t=24666>) als auch ein Artikel aus den FAQ http://www.dclp-faq.de/q/q-code-upload.html

Hat jemand ne Ahnung was ich falsch mache?

Viele Grüße
Andreas

  1. Moin,

    Zunächst mal funktionieren deine Zeilenenden bestenfalls zufällig. RFC 2616 definiert dass die einzig wahren Zeilenenden innerhalb HTTP CRLF sind, also \0x0D\0x0A in PHP (oder such dir ein anderes Zahlensystem). (Und ja, ich habe das in der Vergangenheit auch öfter mal falsch vorgemacht. Sorry dafür.)

    Dann: Du gibst vor HTTP 1.1 zu sprechen, und das kann dir viele Probleme bereiten, mindestens eins davon dürfte die Ursache sein. a) HTTP 1.1-Verbindungen werden normalerweise mit Keep-Alive betrieben (das ist relativ leicht durch Connection: Close loszuwerden) und b) HTTP 1.1-Clients müssen Chunked-Encoding verstehen können. Die genaue Vorgehensweise dafür kannst du im genannten RFC nachlesen, aber im Prinzip wird dabei die Länge eines Chunks (undzwar einfach so, und nicht als schöne ASCII-Zahl, da können dann schonmal nicht druckbare Zeichen rauskommen) gefolgt von einem Chunk dieser Länge, gefolgt von der nächsten Länge + Chunk usw. gesendet. Den Abschluss bildet ein besonderer Wert, der mir grade entfallen ist. Wenn man Chunked nicht versteht, kriegt man zwar auch die Seite zu sehen, aber durchsetzt mit lauter komischen (evt. nicht druckbaren) Zeichen.

    Mach also erstmal aus dem HTTP 1.1 ein 1.0 und sieh dann weiter.

    --
    Henryk Plötz
    Grüße von der Ostsee

    1. Hi!

      Zunächst mal funktionieren deine Zeilenenden bestenfalls zufällig. RFC 2616 definiert dass die einzig wahren Zeilenenden innerhalb HTTP CRLF sind, also \0x0D\0x0A in PHP (oder such dir ein anderes Zahlensystem). (Und ja, ich habe das in der Vergangenheit auch öfter mal falsch vorgemacht. Sorry dafür.)

      Ohha! Naja, selbiges habe ich wohl unten falsch gemacht. Kannst Du mir mal sagen wie man sowas "umrechnet"? Also CRLF in \0x0D\0x0A ?

      Warum eigentlich "keep-Alive"? Ich dachte immer HTTP wäre zustandslos, was soll dann sowas überhaupt?

      Mach also erstmal aus dem HTTP 1.1 ein 1.0 und sieh dann weiter.

      Tatsächlich, und die Umbrüche sind noch wie sie waren, aber die solte ich dann trotzdem noch ändern, habe ich nur noch nirgends gehört(Manual, FAQ...), oder hat der Header "Accept-Charset: iso-8859-1,*,utf-8\n" was damit zu tun?

      Aber ganz klappt es immer noch nicht:

      [_FILES] => Array
              (
                  [da_name] => Array
                      (
                          [name] => da_filename
                      )

      )

      da stimmt wohl was nicht ;-) Aber ich habe mich doch an die Vorgaben gehalten, oder?

      Ich habe es gerade nochmal mit Deinen Zeilenumbrüchen versucht - nix - Timeout.

      So siehts aus:

      $data = $boundary."\0x0D\0x0A";
      $data .= "Content-Disposition: form-data; ";
      $data .= "name="$name"; ";
      $data .= "filename="$filename"\0x0D\0x0A";
      $data .= "Content-Type:text/plain\0x0D\0x0A\0x0D\0x0A";
      $data .= "$gzstring\0x0D\0x0A";

      $header = "POST $path HTTP/1.0\0x0D\0x0A";
      $header .= "Host: $host\0x0D\0x0A";
      $header .= "Content-length: ".strlen($data)."\0x0D\0x0A";
      $header .= "Content-type: multipart/form-data; boundary=$boundary\0x0D\0x0A\0x0D\0x0A";
      $header .= $data;
      $header .= $boundary."--\0x0D\0x0A";

      Grüße
      Andreas

      1. Moin,

        Ohha! Naja, selbiges habe ich wohl unten falsch gemacht. Kannst Du mir mal sagen wie man sowas "umrechnet"? Also CRLF in \0x0D\0x0A ?

        CR ist Carriage Return, also Zeichen 13, hexadezimal demnach 0x0D. LF ist Line Feed also Zeichen 10, hexadezimal 0x0A. (Das ist jetzt die Schreibweise für Zahlen. Wenn es in einem String auftauchen soll, schreibt man \x0D bzw \x0A, die Null kann weggelassen werden.)

        Warum eigentlich "keep-Alive"? Ich dachte immer HTTP wäre zustandslos, was soll dann sowas überhaupt?

        Ist es auch. Da aber sonst für jede HTTP-Anfrage eine neue TCP-Verbindung geöffnet werden muss, was unter Umständen erheblich Zeit kostet (mindestens 3 mal die Zeit von einem zum anderen Ende) lässt man die eine TCP-Verbindung einfach offen und sendet mehrere Anfragen darüber (beim Apache zum Beispiel defaultmäßig bis zu 100). Das hat aber noch überhaupt nichts mit 'HTTP-Verbindungen' zu tun, es ist lediglich eine (entbehrliche) Abkürzung. Wenn Server und Client HTTP richtig können, können sie sogar Pipelining machen, d.h. alle Anfragen hintereineinanderweg in der Verbindung senden, ohne auf die Antworten zu warten, die kommen dann, wenn der Server soweit ist.

        da stimmt wohl was nicht ;-) Aber ich habe mich doch an die Vorgaben gehalten, oder?

        Ja, zwei Kleinigkeiten sind mir aufgefallen: a) im zuständigen RFC 1867 ist ein Komma statt eines Semikolons beim Content-type: multipart/form-data, boundary=bla (aber das scheint kein Problem zu sein) und b) Wenn du die Boundary später verwendest, müssen jeweils noch zwei Striche davor.

        Folgender Ausschnitt funktioniert:

        define(CRLF, "\xD\xA");

        $data = "--".$boundary.CRLF;
         $data .= "Content-Disposition: form-data; ";
         $data .= "name="$name"; ";
         $data .= "filename="$filename"".CRLF;
         $data .= "Content-Type: text/plain".CRLF.CRLF;
         $data .= $gzstring.CRLF;

        $header = "POST $path HTTP/1.0".CRLF;
         $header .= "Host: $host".CRLF;
         $header .= "Content-length: ".strlen($data).CRLF;
         $header .= "Content-type: multipart/form-data, boundary=$boundary".CRLF.CRLF;
         $header .= $data;
         $header .= "--".$boundary."--".CRLF;

        --
        Henryk Plötz
        Grüße von der Ostsee

        1. Hi!

          define(CRLF, "\xD\xA");

          $data = "--".$boundary.CRLF;
          $data .= "Content-Disposition: form-data; ";
          $data .= "name="$name"; ";
          $data .= "filename="$filename"".CRLF;
          $data .= "Content-Type: text/plain".CRLF.CRLF;
          $data .= $gzstring.CRLF;

          $header = "POST $path HTTP/1.0".CRLF;
          $header .= "Host: $host".CRLF;
          $header .= "Content-length: ".strlen($data).CRLF;
          $header .= "Content-type: multipart/form-data, boundary=$boundary".CRLF.CRLF;
          $header .= $data;
          $header .= "--".$boundary."--".CRLF;

          Danke Dir! jetzt bekomme ich immerhin schon:

          [_FILES] => Array
                  (
                      [da_name] => Array
                          (
                              [name] => da_filename
                              [type] => text/plain
                          )

          )

          Nur wo bleiben die Daten selbst, bzw. der temp-name?

          Grüße
          Andreas

          1. Moin,

            Nur wo bleiben die Daten selbst, bzw. der temp-name?

            Des gibts doch nicht, bist du dir sicher dass in deinem Webserver nicht irgendwo ein Wurm drin ist? Mal einen Apache-Neustart gemacht, so rein provisorisch meine ich? Errorlog anschauen? Uploadverzeichnis richtig gesetzt?

            Also hier sind meine Skripte:
            test.php:
            <?php

            $host = "servername";
             $path = "/testload.php";
             $boundary ="blak";

            define(CRLF, "\xD\xA");

            $name = "da_name";
             $filename = "da_filename";
             $gzstring = "HIER_SOLL_MAL_EIN_GZ-STRING_HIN";

            $data = "--".$boundary.CRLF;
             $data .= "Content-Disposition: form-data; ";
             $data .= "name="$name"; ";
             $data .= "filename="$filename"".CRLF;
             $data .= "Content-Type: text/plain".CRLF.CRLF;
             $data .= $gzstring.CRLF;

            $header = "POST $path HTTP/1.0".CRLF;
             $header .= "Host: $host".CRLF;
             $header .= "Content-length: ".strlen($data).CRLF;
             $header .= "Content-type: multipart/form-data, boundary=$boundary".CRLF.CRLF
            ;
             $header .= $data;
             $header .= "--".$boundary."--".CRLF;

            $fp = fsockopen($host, 80);
                fputs($fp, $header);

            while(!feof($fp)) {
                    $res .= fread($fp,1);
                }
                fclose($fp);

            echo $res;
            ?>

            testload.php:
            <?php
            echo "<pre>";
            print_r($_FILES);
            echo "</pre>";
            ?>

            und die generierte Ausgabe:

            HTTP/1.1 200 OK Date: Sun, 29 Sep 2002 02:55:19 GMT Server:
               Apache/1.3.26 (Unix) X-Powered-By: PHP/4.2.2 Connection: close
               Content-Type: text/html
            Array
            (
                [da_name] => Array
                    (
                        [name] => da_filename
                        [type] => text/plain
                        [tmp_name] => /tmp/httpd/phphHaGMC
                        [error] => 0
                        [size] => 31
                    )

            )

            Mehr fällt mir dazu im Moment nicht ein.

            --
            Henryk Plötz
            Grüße von der Ostsee

            1. Hi!

              Ich weiß es auch nicht, ich glaub ich dreh langsam am Rad. Ich habe Dein Script 1:1 kopiert, aber mit demselben Ergebnis. Sowohl vom Linux-Rechner aus als auch vom Windows-Rechner. Ich habe mir den Traffic nochmal angeguckt, ich sehe beim besten Willen keinen Unterschied zwischen diesem Script, und einem gewöhnlichen Upload, wo dann aber die Daten zur Verfügung stehen. Ich verstehe es nicht!!!!

              OK, wieder einige Tests später, bin drauf gekommen das meine Contend-Angabe immer zu wenig war, habe mal bei einem Origuinalen Upload abgezählt, da war der letzte bundary auch mit bei, also habe ich das jetzt so geschrieben:

              <?php

              $host = "www.server.de";
               $path = "/test.php";
               $boundary ="blak";

              define(CRLF, "\xD\xA");

              $name = "da_name";
               $filename = "da_filename";
               $gzstring = "HIER_SOLL_MAL_EIN_GZ-STRING_HIN";

              $data = $boundary.CRLF;
               $data .= "Content-Disposition: form-data; ";
               $data .= "name="$name"; ";
               $data .= "filename="$filename"".CRLF;
               $data .= "Content-Type: text/plain".CRLF.CRLF;
               $data .= $gzstring.CRLF;
               $data .= "--".$boundary."--".CRLF;

              $header = "POST $path HTTP/1.0".CRLF;
               $header .= "Host: $host".CRLF;

              $header .= "Content-type: multipart/form-data; boundary=$boundary".CRLF;
               $header .= "Content-length: ".strlen($data).CRLF.CRLF;

              $header .= $data;

              $fp = fsockopen($host, 80);
                  fputs($fp, $header);

              while(!feof($fp)) {
                      $res .= fread($fp,1);
                  }
                  fclose($fp);

              echo $res;
              ?>

              und siehe da es geht:

              [_FILES] => Array
                      (
                          [da_name] => Array
                              (
                                  [name] => da_filename
                                  [type] => text/plain
                                  [tmp_name] => /tmp/phpoKZoyc
                                  [size] => 31
                              )

              )

              Weiß gar nicht wie ich Dir danken soll! Alleine hätte ich es wohl nicht geschafft! Wobei ich mich jetzt ernsthaft frage warum es bei Dir funktioniert hat und bei mir nicht?!

              Was hälst Du von einer htaccess Authentifizierung:

              $header .= "Authorization: Basic ".base64_encode("$username:$password").CRLF;

              Ich habe übrigens mal ein bisschen in der OHP-Doku gelesen, sehr viele Fehler in zusammenhang mit Ubertragung binärer Daten entstehen wohl tatsächlich durch die "Zeilenenden" und in PHP kann man das komplett umgehen wenn man die contrend-length angibt, wobei der Apache auf der anderen Seite ja auch noch ein wörtchen mitzusprechen hat ;-)

              ich versuche jetzt einfach mal einen gz-String zu übertragen, vielleicht klappts ja einfach so!

              Nochmals vielen Dank und schöne Grüße,
              Andreas

              1. Moin,

                OK, wieder einige Tests später, bin drauf gekommen das meine Contend-Angabe immer zu wenig war, habe mal bei einem Origuinalen Upload abgezählt, da war der letzte bundary auch mit bei, also habe ich das jetzt so geschrieben:

                Ja, das ist mir vorher auch aufgefallen. Ich hatte dann überlegt, ob die Content-Length-Angabe nicht ohnehin überflüssig ist, da durch die Boundary ja klar ist, wann Schluss ist. Als es dann aber ohne Content-Length nicht ging, habe ich den Gedanken verworfen (und die fehlerhafte Länge gleich mit).

                Was hälst Du von einer htaccess Authentifizierung:

                $header .= "Authorization: Basic ".base64_encode("$username:$password").CRLF;

                Ist ok. Das Zielskript sollte sowieso keine Daten von jemand anderem als localhost entgegennehmen (durch den Tunnel scheinen ja alle Anfragen von dort zu kommen) und über eine weitere Zugangssicherung musst du dir dann höchstens noch Sorgen machen, wenn du dir den Server mit Anderen teilst. Ein geheimer String den alle Clients kennen, sollte dafür ausreichen.

                ich versuche jetzt einfach mal einen gz-String zu übertragen, vielleicht klappts ja einfach so!

                Sollte eigentlich. Sicherheitshalber setz' den Content-Type mal auf application/octet-stream, damit da nicht noch irgend ein Programm auf dumme Ideen kommt.

                Noch was: Die Boundary darf logischerweise nirgendwo in den übertragenen Daten vorkommen, was bei den hier beispielhaft verwendeten 4 Bytes schon mal passieren könnte (unendlich viele Affen und so ;-). Du solltest also entweder vorher einmal überprüfen ob sie drin ist und sie ggbf. ändern oder einfach einen längeren wilderen String nehmen, um die Wahrscheinlichkeit zu senken.

                --
                Henryk Plötz
                Grüße von der Ostsee

                1. Hi!

                  Was hälst Du von einer htaccess Authentifizierung:

                  $header .= "Authorization: Basic ".base64_encode("$username:$password").CRLF;

                  Ist ok. Das Zielskript sollte sowieso keine Daten von jemand anderem als localhost entgegennehmen (durch den Tunnel scheinen ja alle Anfragen von dort zu kommen) und über eine weitere Zugangssicherung musst du dir dann höchstens noch Sorgen machen, wenn du dir den Server mit Anderen teilst. Ein geheimer String den alle Clients kennen, sollte dafür ausreichen.

                  Ja, aber ich habe ja inzwischen doch mal testweise PHP4.3 am laufen und werde gleich mal SSL mit fsockopen proboieren - ich denke das wird die langfristige Lösung. Daher brauche ich auch eine gute authentigizierung, wobei vielleicht htaccess nicht das beste ist, oder? Am besten mache ich das wohl im Script selbst. Bei SSH brauche ich mich um die authentifizierung nicht tu kümmern, da reicht die Abfrage nach localhost würde ich sagen, aber über SSL geht das ja nicht! Wie übertrage ich wohl am besten weitere 2-3 weitere Variablen? Das einfachste wäre wohl im Query-String, oder? Aber ich weiß ja wie ich herausbekomme wie der Browser das macht und das mache ich einfach nach ;-)

                  ich versuche jetzt einfach mal einen gz-String zu übertragen, vielleicht klappts ja einfach so!

                  Sollte eigentlich. Sicherheitshalber setz' den Content-Type mal auf application/octet-stream, damit da nicht noch irgend ein Programm auf dumme Ideen kommt.

                  OK. Aber was soll ich sagen, das kompimieren hat diesmal tadellos geklappt! Perfekt! Das war aber alles in allem eine "schwere Geburt"!

                  Noch was: Die Boundary darf logischerweise nirgendwo in den übertragenen Daten vorkommen, was bei den hier beispielhaft verwendeten 4 Bytes schon mal passieren könnte (unendlich viele Affen und so ;-). Du solltest also entweder vorher einmal überprüfen ob sie drin ist und sie ggbf. ändern oder einfach einen längeren wilderen String nehmen, um die Wahrscheinlichkeit zu senken.

                  Jaja, da nehme ich sowas wie vorher!

                  Vielen Dank nochmal für alles, hast mir sehr geholfen! Naja, ganz fertig bin ich noch nicht, die ssl-Variante mit fsockopen scheint noch nicht zu funktionieren, und die SSH-Variante funktioniert ebenfalls nicht ;-)
                  Sieht fast so aus als hätten die den Apache für localhost gesperrt, zumindest bekommem ich vom Server einen 403. Bie der fsockopen-Geschichte bekomme ich "no SSL support in this build", obwohl oopenssl läuft, aber anscheinend ist man noch nicht so weit, zumindest bei Windows noch nicht! Naja, ich muß aber glaube ich langsam mal schlafen ;-) Schläfst Du nie?

                  Grüße
                  Andreas

                  1. Hallo!

                    Sieht denn der Header bei SSL anders aus?

                    Wenn ich

                    fsockopen ("https://www.server.de",443);

                    angebe bekomme ich folgende Meldung zurück:

                    HTTP/1.1 400 Bad Request Date: Sun, 29 Sep 2002 08:32:02 GMT Server: Apache/df-exts 1....

                    Bad Request
                    Your browser sent a request that this server could not understand.

                    Client sent malformed Host header

                    Wenn ich dagegen

                    fsockopen ("ssl://www.server.de",443); angebe wie auch in der Doku beschreiben, dann bekomme ich:

                    Warning: fsockopen() [function.fsockopen]: no SSL support in this build in c:\www\test.php on line 39

                    Warning: fsockopen() [function.fsockopen]: unable to connect to www.server.de:443 in c:\www\test.php on line 39
                    ERROR: 0 - Der Vorgang wurde erfolgreich beendet.

                    letzteres ist:
                     echo "ERROR: $errno - $errstr<br>\n"
                    Erfolgreich war das aber nicht, denn dan müßte ich irgendeine aAusgabe bekommen, außer der Meldung bleibt der Schirm leer!

                    Naja, kann  irgendwie alles nicht wahr sein. Nicht ein Schritt klappt mal so auf Anhieb!

                    Grüße
                    Andreas

                    1. Moin,

                      Daher brauche ich auch eine gute authentigizierung, wobei vielleicht htaccess nicht das beste ist, oder?

                      Ja, das wollte ich ausdrücken. Bei .htaccess ist crypt() im Spiel was die Länge des Passwortes u.U. auf 8 Zeichen beschränkt. Da das Passwort ja niemand eintippen muss, kann und sollte es länger sein.

                      Am besten mache ich das wohl im Script selbst. Bei SSH brauche ich mich um die authentifizierung nicht tu kümmern, da reicht die Abfrage nach localhost würde ich sagen, aber über SSL geht das ja nicht!

                      Also SSL selbst kennt Client-Zertifikate, aber dass dürftest du mit den in PHP eingebauten Funktionen wohl kaum benutzen können. Da wäre noch das von mir schon vor längerer Zeit erwähnte openssl-Kommandozeilenprogramm, das hat aber wieder den Haken dass du popen() zum Lesen und Schreiben brauchst.

                      Wie übertrage ich wohl am besten weitere 2-3 weitere Variablen? Das einfachste wäre wohl im Query-String, oder? Aber ich weiß ja wie ich herausbekomme wie der Browser das macht und das mache ich einfach nach ;-)

                      Genau, oder einfach vor dem Datenbankdump eine Zeile mit dem geheimen Wort.

                      Sieht fast so aus als hätten die den Apache für localhost gesperrt, zumindest bekommem ich vom Server einen 403.

                      Hoe, mal ins Errorlog geschaut?

                      Bie der fsockopen-Geschichte bekomme ich "no SSL support in this build", obwohl oopenssl läuft, aber anscheinend ist man noch nicht so weit, zumindest bei Windows noch nicht!

                      Hast du es denn einkompiliert? Schau mal in der Ausgabe von phpinfo() nach, da sollte sowas eigentlich auftauchen.

                      Naja, ich muß aber glaube ich langsam mal schlafen ;-) Schläfst Du nie?

                      Doch, von meinem letzten Post bis vor etwa einer Stunde.

                      Sieht denn der Header bei SSL anders aus?

                      Eigentlich nicht. Zuerst kommt das SSL-Gezeugs (Austausch der Zertifikate, festlegen der Verschlüsselung und so) und dann in der Verschlüsselung ganz normales HTTP.

                      fsockopen ("https://www.server.de",443);

                      HTTP/1.1 400 Bad Request Date: Sun, 29 Sep 2002 08:32:02 GMT Server: Apache/df-exts 1....

                      Das riecht als würdest du SSL mit einem HTTP-Port sprechen. Jag mal deinen Sniffer drauf und schau im Errorlog nach.

                      Warning: fsockopen() [function.fsockopen]: no SSL support in this build in c:\www\test.php on line 39

                      Das hingegen riecht wieder als würdest du gar kein SSL in dem PHP haben. -> Frag phpinfo().

                      ERROR: 0 - Der Vorgang wurde erfolgreich beendet.

                      Error 0 bedeutet afaik nur, dass der Fehler noch vor dem Verbindungsaufbau auftrat. Normalerweise bedeutet das, dass die Namensauflösung schief gegangen ist, es kann natürlich auch heissen, dass das Protokoll nicht unterstützt wird, so wie er sagt.

                      Nicht ein Schritt klappt mal so auf Anhieb!

                      Naja, mein Vater sagt immer, dass etwas das auf Anhieb funktioniert höchst verdächtig ist. Da kann dann irgendwas nicht stimmen und es wird idR schnell kaputtgehen. :-)

                      --
                      Henryk Plötz
                      Grüße von der Ostsee

                      1. Hi!

                        Genau, oder einfach vor dem Datenbankdump eine Zeile mit dem geheimen Wort.

                        Ja stimmt, das wird das beste sein. Hatte auch mit dem Gedanken gespielt dem Remoter-Server zunächst über SSH die eigene IP mitzuteilen, da ich nicht hinter nem Proxy hänge ist das schon recht sicher, wenn ich die dann nach Beendigung lösche. Anhand der IP könnte der Server dann ja die Anfrage validieren. Ein lanhges Kennwort könnte ich ja vielleicht auch als User-Agent String übertragen ;-) Mal schauen, ich denke ich weiß jetzt wie ich eine vernünftige Authentifizierung über SSL hinbekomme!

                        Sieht fast so aus als hätten die den Apache für localhost gesperrt, zumindest bekommem ich vom Server einen 403.

                        Hoe, mal ins Errorlog geschaut?

                        Kann ich leider nicht, ich habe nur Zugriff auf die 500er über ein spezielles Interface. Ich habe das Script mal auf den anderen Server übertragen und da ausgeführt(Zugriff auf 127.0.0.1:80), und ebenfalls 403. Dasselbe Script bei mir lokal auf 127.0.0.1:80(also nicht durch den Tunnel), funktioniert. Daher wird es da irgendeine Beschränkuing geben, warum auch immer, das werde ich direkt morgen früh erroieren! Also ein Tunnen zum Apache klappt schonmal nicht. Vielleicht muß ich mir tatsächlich einen eigenen "Socket-Server" basteln, da wäre ich auch nicht mehr auf http beschränkt! Ist nur fraglich ob man sowas darf, kann ja ne nette Sicherheitslücke sein ;-)

                        Bie der fsockopen-Geschichte bekomme ich "no SSL support in this build", obwohl oopenssl läuft, aber anscheinend ist man noch nicht so weit, zumindest bei Windows noch nicht!

                        Hast du es denn einkompiliert? Schau mal in der Ausgabe von phpinfo() nach, da sollte sowas eigentlich auftauchen.

                        Ich habe meinen Lebtag noch nichts kompiliert, und kompilieren müssen,  ich habe einfach die vorkompilierte Version von PHP verwendet, da muß ich lediglich die Extension in der php.ini freischalten und dafür sorgend das die entsprechende DLL verfügbar ist, was sohl der Fall ist da ich sonst einen Fehler bekäme, aber auch phpinfo() zeigt mir das openssl-Modul an.

                        Naja, ich muß aber glaube ich langsam mal schlafen ;-) Schläfst Du nie?

                        Doch, von meinem letzten Post bis vor etwa einer Stunde.

                        Aber dann bist Du zur Zeit wohl nicht in Europa, oder?

                        Sieht denn der Header bei SSL anders aus?

                        Eigentlich nicht. Zuerst kommt das SSL-Gezeugs (Austausch der Zertifikate, festlegen der Verschlüsselung und so) und dann in der Verschlüsselung ganz normales HTTP.

                        Naja, da bin ich ja beruhigt! Also den Rest müsste ja eigentlich PHP machen wenn ich das richtig verstanden habe. Vielleicht funktioniert php_curl ja in dieser Version, wäre ja immerhin auch noch eine Möglichkeit!

                        fsockopen ("https://www.server.de",443);

                        HTTP/1.1 400 Bad Request Date: Sun, 29 Sep 2002 08:32:02 GMT Server: Apache/df-exts 1....

                        Das riecht als würdest du SSL mit einem HTTP-Port sprechen. Jag mal deinen Sniffer drauf und schau im Errorlog nach.

                        0004  F9 94 E6 56 4E E5 50 18 7F FF C2 E1 00 00 50 4F    ù”æVNåP.ÿÂá..PO
                        0005  53 54 20 2F 73 6F 63 6B 74 65 73 74 2E 70 68 70    ST /socktest.php
                        0006  20 48 54 54 50 2F 31 2E 30 0D 0A 48 6F 73 74 3A     HTTP/1.0..Host:
                        0007  20 68 74 74 70 73 3A 2F 2F 77 77 77 2E 6B 6E 65     https://www.kne
                        0008  74 2D 73 79 73 74 65 6D 73 2E 64 65 0D 0A 43 6F    t-systems.de..Co
                        0009  6E 74 65 6E 74 2D 74 79 70 65 3A 20 6D 75 6C 74    ntent-type: mult
                        000A  69 70 61 72 74 2F 66 6F 72 6D 2D 64 61 74 61 3B    ipart/form-data;
                        000B  20 62 6F 75 6E 64 61 72 79 3D 62 6C 61 6B 0D 0A     boundary=blak..
                        000C  43 6F 6E 74 65 6E 74 2D 6C 65 6E 67 74 68 3A 20    Content-length:
                        000D  32 36 31 0D 0A 0D 0A 62 6C 61 6B 0D 0A 43 6F 6E    261....blak..Con
                        000E  74 65 6E 74 2D 44 69 73 70 6F 73 69 74 69 6F 6E    tent-Disposition
                        000F  3A 20 66 6F 72 6D 2D 64 61 74 61 3B 20 6E 61 6D    : form-data; nam
                        0010  65 3D 22 64 61 5F 6E 61 6D 65 22 3B 20 66 69 6C    e="da_name"; fil
                        0011  65 6E 61 6D 65 3D 22 64 61 5F 66 69 6C 65 6E 61    ename="da_filena
                        0012  6D 65 22 0D 0A 43 6F 6E 74 65 6E 74 2D 54 79 70    me"..Content-Typ
                        0013  65 3A 20 61 70 70 6C 69 63 61 74 69 6F 6E 2F 6F    e: application/o
                        0014  63 74 65 74 2D 73 74 72 65 61 6D 0D 0A 0D 0A 78    ctet-stream....x

                        Mag sein das ich blind bin, aber wo steht da der Port 443 den ich richtigerweise fsockopen() mitgegeben habe? 443 ist 100%ig der SSL-Port! IWe gesagt komme ich da leider nicht an die error-log. Porblem ist das die Error.log nicht nach Kunden getrennt werden kann.

                        Warning: fsockopen() [function.fsockopen]: no SSL support in this build in c:\www\test.php on line 39

                        Das hingegen riecht wieder als würdest du gar kein SSL in dem PHP haben. -> Frag phpinfo().

                        Ich habe nochmal news.txt gelesen, da steht definitiv:

                        • PHP now has a new stream system that allows it to do some clever stuff with
                            fopen() and fsockopen().  As a result:
                            . URL wrappers natively supports https:// URLs
                            . fsockopen() adds support for ssl:// and tls:// connections via TCP/IP

                        Wie gesagt, openssl-modul ist gegeben. Woher weiß ich was ich da falsch mache? Ich habe keine Ahnung wo ich da nach nem Fehler suchen soll, ist mir ein Rätsel! Vielleicht funkitoniert der Teil auch noch nicht unter windows, aber würde das dann in den news.txt meiner Version stehen? Wohl kaum!

                        Nicht ein Schritt klappt mal so auf Anhieb!

                        Naja, mein Vater sagt immer, dass etwas das auf Anhieb funktioniert höchst verdächtig ist. Da kann dann irgendwas nicht stimmen und es wird idR schnell kaputtgehen. :-)

                        Jajaja, Sprüche ;-) So langsam wie die letzten Tage bin ich noch nie vorwärts gekommen. War aber wenigstens lehrreich(vor allem dank Dir!)

                        Viele Grüße
                        Andreas

                        1. Moin,

                          Also ein Tunnen zum Apache klappt schonmal nicht.

                          Das kommt mir sehr verdächtig vor, sprich den Provider mal darauf an.

                          Aber dann bist Du zur Zeit wohl nicht in Europa, oder?

                          Wieso nicht? Es sind grade Semesterferien, da ist mir die Tageszeit relativ egal.

                          Das riecht als würdest du SSL mit einem HTTP-Port sprechen. Jag mal deinen Sniffer drauf und schau im Errorlog nach.

                          0004  F9 94 E6 56 4E E5 50 18 7F FF C2 E1 00 00 50 4F    ù”æVNåP.

                          1. Hey!

                            Also ein Tunnen zum Apache klappt schonmal nicht.

                            Das kommt mir sehr verdächtig vor, sprich den Provider mal darauf an.

                            JA, das ist so: Ich muß die offizielle IP meines Servers nehmen. Damit wäre zumindest die Verschlüsselung erreicht, nur die Authentifiziereung durch SSH ist natürlich hinfällig, aber da hatten wir ja schon von gesprochen wie das machbar ist. Nur das was ich nucht verstehe, wieso kann man nur dem Apachen Daten schicken? Ich habe ja per plink vollen Zugriff auf die Kommandozeile, gibt es da wirklich keine andere Möglichkeit große Mengen Daten so zu übertragen? Von mir aus ohne Tunnel, sondern direkt! Oder halt mit Tunnel, aber dann ginge es wirklich nur mit einem eigenen kleinen Server der an einem Port lauscht. Wobei ich dieser Version durchaus nicht abgeneigt bin muß ich sagen ;-)

                            Aber dann bist Du zur Zeit wohl nicht in Europa, oder?

                            Wieso nicht? Es sind grade Semesterferien, da ist mir die Tageszeit relativ egal.

                            Jajaja, immer diese Studenten, nichts zu tun, was? *g*
                            Aber ich mag es auch Nachts zu arbeiten, ist alles viel ruhiger und entspannter ;-)

                            Grüße
                            Andreas

                            Das riecht als würdest du SSL mit einem HTTP-Port sprechen. Jag mal deinen Sniffer drauf und schau im Errorlog nach.

                            0004  F9 94 E6 56 4E E5 50 18 7F FF C2 E1 00 00 50 4F    ù“æVNåP.

                            1. Moin,

                              Nur das was ich nucht verstehe, wieso kann man nur dem Apachen Daten schicken? Ich habe ja per plink vollen Zugriff auf die Kommandozeile, gibt es da wirklich keine andere Möglichkeit große Mengen Daten so zu übertragen?

                              Du könntest mal schauen, ob auf dem Rechner netcat (bzw. nc) installiert ist, oder es nachinstallieren. Das ist ein kleines Kommandozeilenutility das auch an einem Port lauschen und alles was es dort empfängt an die Standardausgabe geben kann. Von dort aus kannst du sie dann ganz normal mit > in eine Datei leiten. Lies dir einfach mal die manpage durch. Du könntest dann auch bei PuTTY links unter SSH rechts ein Kommando eingeben was direkt nach der Verbindung gestartet wird, wenn das dann nc mit den jeweiligen Parametern ist, kannst du wieder die bekannt kurze plink-Zeile verwenden. Als Port suchst du dir einfach irgendwas hohes aus. Wenn der dann aber zufällig belegt ist, hast du ein Problem.

                              Aber ich mag es auch Nachts zu arbeiten, ist alles viel ruhiger und entspannter ;-)

                              Ack, vor allem störe ich da meinen Vater nicht, wenn er am Computer sein will und meine Eltern stören mich nicht.

                              --
                              Henryk Plötz
                              Grüße von der Ostsee

                              1. Hallo!

                                Du könntest mal schauen, ob auf dem Rechner netcat (bzw. nc) installiert ist, oder es nachinstallieren. Das ist ein kleines Kommandozeilenutility das auch an einem Port lauschen und alles was es dort empfängt an die Standardausgabe geben kann.

                                Schade, leider nicht vorhanden. Sowas wäre schon praktisch. Aber Moment! Wenn ich mich nicht irre kann PHP Daten über die Standardeingabe erhalten. Könnte ich nicht  mit lokalem php plink und damit so ein remote-PHP-Script starten und mit popen plink die Daten an die Standardeingabe geben... aber ich glaube das kann plink nicht, gel? So was ärgerliches. Dann gucke ich mir halt nochmal an was PHP so mit Sockets anstellen kann!

                                Aber ich mag es auch Nachts zu arbeiten, ist alles viel ruhiger und entspannter ;-)

                                Ack, vor allem störe ich da meinen Vater nicht, wenn er am Computer sein will und meine Eltern stören mich nicht.

                                Ja, nur das ich dann am nächten Tag meist nicht schlafe, höchstens 2-3 Stunden, udn wenn ich das öfter mache bin ich doch recht fertig ;-)
                                Man ist ja schließlich keine 16 mehr!

                                Und nochmals Danke für Deine Hilfe!

                                Grüße
                                Andreas

                                1. Moin,

                                  Schade, leider nicht vorhanden. Sowas wäre schon praktisch. Aber Moment! Wenn ich mich nicht irre kann PHP Daten über die Standardeingabe erhalten. Könnte ich nicht  mit lokalem php plink und damit so ein remote-PHP-Script starten und mit popen plink die Daten an die Standardeingabe geben... aber ich glaube das kann plink nicht, gel?

                                  Doch, das müsste gehen. Du kannst auf der anderen Seite PHP als Skript-Sprache verwenden (wenn die CGI-Version zumindest zusätzlich installiert ist), und es dann von plink starten lassen. Die zugehörige Konfiguration ist in PuTTY links SSH und rechts remote command. Wenn du plink dann mit popen() öffnest, solltest du nach kurzer Zeit Daten direkt an die Standardeingabe des PHP-Skriptes senden können.
                                  Zwei Probleme: a) Das alte popen()-Problem, dass du entweder schreiben oder lesen kannst bleibt bestehen; und selbst wenn sich das ändert (popen() zum Lesen öffnen und Ausgabe in eine Datei schreiben etwa), gibt es noch b) Ich bin mir nicht sicher, ob diese Kette 8bit-sicher ist. Falls Probleme auftreten, solltest du versuchen keine Binärdaten drüberzuschicken. Möglicher Workaround: Daten in PHP mit gzcompress() komprimieren und mit base64_encode() kodiert durch die Leitung schicken. Dafür in PuTTY Kompression aktivieren, um die Bas64-Verluste auszugleichen.

                                  So was ärgerliches. Dann gucke ich mir halt nochmal an was PHP so mit Sockets anstellen kann!

                                  Ja, das würde beide Probleme erledigen. Nur, dass die Socketfunktionen noch größtenteils als experimentell gekennzeichnet sind.

                                  Ja, nur das ich dann am nächten Tag meist nicht schlafe, höchstens 2-3 Stunden, udn wenn ich das öfter mache bin ich doch recht fertig ;-)

                                  Hu? Also ich kann problemarm nachts auf sein und tagsüber schlafen (heute ist eine Ausnahme, da ich einen Termin hatte).

                                  Man ist ja schließlich keine 16 mehr!

                                  Naja, da müsstest du aber über 50 sein, damit das zum Problem wird. In dem Alter beginnen sich nämlich die Schlafgewohnheiten zu ändern: Fast kein Nicht-REM-Schlaf mehr (später gar keiner mehr) und daher in der Regel _kürzere_ Gesamtschlafdauer.

                                  --
                                  Henryk Plötz
                                  Grüße von der Ostsee

                        2. Moin,

                          Mist, Mozilla hat das Posting auf dem Gewissen. Anscheinend hat er den String bei einem der Zeichen (scheinbar dem 0x7F) die du reingepastet hast beendet.

                          Was ich sagen wollte:

                          0004  F9 94 E6 56 4E E5 50 18 7F FF C2 E1 00 00 50 4F    {gesnippt}

                          Leider hast du den Anfangsteil der die TCP- und IP-Header mit unter anderem der Portnummer enthält größtenteils weggeschnitten. Das ist aber auch egal, denn das sieht nicht verschlüsselt aus, ist also kein HTTPS und damit eh ungewollt.

                          0006  20 48 54 54 50 2F 31 2E 30 0D 0A 48 6F 73 74 3A     HTTP/1.0..Host:
                          0007  20 68 74 74 70 73 3A 2F 2F 77 77 77 2E 6B 6E 65     https://www.kne

                          So wie ich RFC 2616 lese, darf der Host:-Header auch keine Protokollangabe enthalten, dieser Header somit tatsächlich kaputt.

                          000D  32 36 31 0D 0A 0D 0A 62 6C 61 6B 0D 0A 43 6F 6E    261....blak..Con

                          Fehlen vor dem blak da nicht noch -- oder bin ich wieder verwirrt?

                          Mag sein das ich blind bin, aber wo steht da der Port 443 den ich richtigerweise fsockopen() mitgegeben habe? 443 ist 100%ig der SSL-Port!

                          Den Port hast du weggeschnitten. ;-)

                          IWe gesagt komme ich da leider nicht an die error-log. Porblem ist das die Error.log nicht nach Kunden getrennt werden kann.

                          Wenn du dir den Server mit anderen Kunden teilst, darfst du dich bei der Authentifizierung ohnehin nicht allein auf die IP-Addresse verlassen, da die ja auch von 127.0.0.1 kommen können.

                          Ich habe nochmal news.txt gelesen, da steht definitiv:

                          • PHP now has a new stream system that allows it to do some clever stuff with
                              fopen() and fsockopen().  As a result:
                              . URL wrappers natively supports https:// URLs
                              . fsockopen() adds support for ssl:// and tls:// connections via TCP/IP

                          Ich habe mir eben auch einen aktuellen PHP-Snapshot gezogen und da ist mir aufgefallen: In dem Text steht, dass URL Wrapper (also fopen(), file()...) mit https gehen sollten, du bei fsockopen aber ssl: oder tls: nehmen musst. Du darfst die beiden Einträge nicht vermixen. Ich habe es auch versucht und scheinbar geht beides nicht, wahrscheinlich ist das Stream-Gezeugs noch nicht fertig. Also würde ich sagen: Schauen warum der SSH-Tunnel nicht geht und warten.

                          Wie gesagt, openssl-modul ist gegeben.

                          Ja, ich habe auch mal eine OpenSSL-Funktion aufgerufen und scheint wirklich drin zu sein, wenn phpinfo() das sagt (zumindest ist mir nichts in Gesicht geflogen). Schau dir also mal http://www.php.net/manual/en/ref.openssl.php an, ob du damit auch weiterkommst, zumal man dafür kein so neues PHP braucht, solange die Extension installiert ist. Wenn du schon dabei bist, kannst du eigentlich auch gleich mcrypt nehmen. Ein Rjindael (==AES) mit ordentlicher Schlüssellänge erscheint mir subjektiv doch deutlich angenehmer als der von openssl_seal() verwendete RC4 (== der Algorithmus der WEP zum Verhängnis wurde).

                          So langsam wie die letzten Tage bin ich noch nie vorwärts gekommen. War aber wenigstens lehrreich(vor allem dank Dir!)

                          Ich danke, da ich auch viel lerne.

                          --
                          Henryk Plötz
                          Grüße von der Ostsee

                          1. Hi!

                            Was ich sagen wollte:

                            0004  F9 94 E6 56 4E E5 50 18 7F FF C2 E1 00 00 50 4F    {gesnippt}

                            Leider hast du den Anfangsteil der die TCP- und IP-Header mit unter anderem der Portnummer enthält größtenteils weggeschnitten. Das ist aber auch egal, denn das sieht nicht verschlüsselt aus, ist also kein HTTPS und damit eh ungewollt.

                            Naja, ich bezweifele das Du da was erkannt hättest, zumindest mein sniffer schreibt da grostes Kauderwelsch! "POST" ist das erste Wort was man lesen kann.

                            0006  20 48 54 54 50 2F 31 2E 30 0D 0A 48 6F 73 74 3A     HTTP/1.0..Host:
                            0007  20 68 74 74 70 73 3A 2F 2F 77 77 77 2E 6B 6E 65     https://www.kne

                            So wie ich RFC 2616 lese, darf der Host:-Header auch keine Protokollangabe enthalten, dieser Header somit tatsächlich kaputt.

                            Ja, das war auch nur ein frei erfundener test mit fsockopen, da ssl:// nicht geklappt hat! Also ist das so auch nicht richtig. Ich versteh zumindest diesesn Fehler, ich schicke den Request an den SSL-Serverport, und da der Header nicht ssl-verschlüsselt und sowieso ganz falsch ist bekomme ich den bad Request. Eine Sackgasse also.

                            000D  32 36 31 0D 0A 0D 0A 62 6C 61 6B 0D 0A 43 6F 6E    261....blak..Con

                            Fehlen vor dem blak da nicht noch -- oder bin ich wieder verwirrt?

                            Nein, Du hast Recht, die Fehlern. Die habe ich beim testen wieder entfernt, denn ich hatte einen Request(File Upload Formular) den Mozilla geschickt hatte mal angesehen und den habe ich versucht genau nachzubilden. Das problem lag ja bei contend-Length, die Unterschiede zu Mozilla und Deiner Version waren halt diese "--" und das ";" statt "," irgendwo ich glaube vor dem ersten booundary. Aber diese Änderungen haben wie gesagt nichst gebracht, und ich habs einfach noch nicht wieder rückgängig gemacht! Aber so wie es da steht hat es mit reinem http funktioniert.

                            Mag sein das ich blind bin, aber wo steht da der Port 443 den ich richtigerweise fsockopen() mitgegeben habe? 443 ist 100%ig der SSL-Port!

                            Den Port hast du weggeschnitten. ;-)

                            Leeider kann ich keien binärdaten lesen, oder was auch immer diese Kauderwelsch zu sagen hatte!

                            Also verstehe ich das Richtig das der Port nichts mit dem http-header zu tun hat sondern nur mit dem TCP/IP header und nur darin enthalten ist? Denn der HTTP Header fängt ja erst bei "POST..." an, oder?

                            IWe gesagt komme ich da leider nicht an die error-log. Porblem ist das die Error.log nicht nach Kunden getrennt werden kann.

                            Wenn du dir den Server mit anderen Kunden teilst, darfst du dich bei der Authentifizierung ohnehin nicht allein auf die IP-Addresse verlassen, da die ja auch von 127.0.0.1 kommen können.

                            Stimmt, aber das kann ich eh vergessen, siehe Posting, ich muß die offizielle IP verwenden.

                            Ich habe nochmal news.txt gelesen, da steht definitiv:

                            • PHP now has a new stream system that allows it to do some clever stuff with
                                fopen() and fsockopen().  As a result:
                                . URL wrappers natively supports https:// URLs
                                . fsockopen() adds support for ssl:// and tls:// connections via TCP/IP

                            Ich habe mir eben auch einen aktuellen PHP-Snapshot gezogen und da ist mir aufgefallen: In dem Text steht, dass URL Wrapper (also fopen(), file()...) mit https gehen sollten, du bei fsockopen aber ssl: oder tls: nehmen musst. Du darfst die beiden Einträge nicht vermixen. Ich habe es auch versucht und scheinbar geht beides nicht, wahrscheinlich ist das Stream-Gezeugs noch nicht fertig. Also würde ich sagen: Schauen warum der SSH-Tunnel nicht geht und warten.

                            Ja, ich habe einfach beides versucht, und ich habe auch vorher in der  Doku gelesen, habe ss:// auch als erstes verucht, ging ja nicht, also habe ich mehr oder weniger aus Verzweiflung mal https:// probiert ;-) Aber ich habe das schon richtig verstanden, nur ein ssl:// davor und den SSL-Port und schon geht derselbe header über SSL, oder?

                            Wie gesagt, openssl-modul ist gegeben.

                            Ja, ich habe auch mal eine OpenSSL-Funktion aufgerufen und scheint wirklich drin zu sein, wenn phpinfo() das sagt (zumindest ist mir nichts in Gesicht geflogen). Schau dir also mal http://www.php.net/manual/en/ref.openssl.php an, ob du damit auch weiterkommst, zumal man dafür kein so neues PHP braucht, solange die Extension installiert ist. Wenn du schon dabei bist, kannst du eigentlich auch gleich mcrypt nehmen. Ein Rjindael (==AES) mit ordentlicher Schlüssellänge erscheint mir subjektiv doch deutlich angenehmer als der von openssl_seal() verwendete RC4 (== der Algorithmus der WEP zum Verhängnis wurde).

                            Ich vermute fast das es darauf hinaus laufen wird. Es war sogar mal im Gespräch das ganze mit GPG zu ver- und entschlüsseln, aber das ist wirklich nicht so einfach, vor allem ist das recht kompliziert auf ein anderes System zu portieren, wegen der Schlüssel, den Einstellungen in GPG... obwohl es da wohl auch eine symetrische Verschlüsselung geben soll, fändest Du das denn besser als mcrypt und SSL und SSH? Aber ich würde ganz gerne innerhalb von PHP bleiben um Probleme mit den Schnittstellen wie bei cURL möglichst aus dem Weg zu gehen.

                            Nunja, ich habe mir also gerade mcrypt mal angesehen.
                            Da steht ja ein komplettes Beispiel: http://www.php.net/manual/en/function.mcrypt-module-open.php

                            Jetzt Frage ich mich wie man deises Beispiel auf 2 Servern verwenden kann, halt auf dem einen verschlüsseln, auf dem anderen entschlüsseln. Das ganze ist abgängig von 3 Variablen:

                            $iv, $key, $td. Die Frage ist ob ich alle 3 Variablen auf dem anderen Servern genau so generieren kann, was vermutlich nicht gehen sollte, da das System sonst recht unsicher wäre, oder?

                            Und sowas im Klartext mit zu übertragen ist noch viel schlimmer!

                            openssl muß ich gestehen verstehe ich nich nicht so recht wie ich das anwenden soll: http://www.php.net/manual/en/function.openssl-seal.php, da ist ja auch ein nettes Beispiel, da steht halt wie ich einen schlüssel erstelle, und dann free key, aber was sollte die ganze Aktion jetzt? Sende ich mit openssl die daten direkt wie mit fsockopen, und der SSL-Server erkennt das selbst und ich habe auf dem entgegennehmenden PHP-Script die Daten ganz normal zur Verefügung, doer muß ich auch hier den Datenstring verschlüsseln, was ja eigentlich reichen würde!

                            So langsam wie die letzten Tage bin ich noch nie vorwärts gekommen. War aber wenigstens lehrreich(vor allem dank Dir!)

                            Ich danke, da ich auch viel lerne.

                            Das freut mich sehr!

                            Viele Grüße
                            Andreas

                            1. Moin,

                              Naja, ich bezweifele das Du da was erkannt hättest,

                              Och, ich hätte RFC 791 und 793 gezückt und mich gefreut die mal auf einen Hexdump loslassen zu können.

                              zumindest mein sniffer schreibt da grostes Kauderwelsch! "POST" ist das erste Wort was man lesen kann.

                              Nimm doch Ethereal.

                              Leeider kann ich keien binärdaten lesen, oder was auch immer diese Kauderwelsch zu sagen hatte!

                              Das wären die IP und TCP-Header gewesen.

                              Also verstehe ich das Richtig das der Port nichts mit dem http-header zu tun hat sondern nur mit dem TCP/IP header und nur darin enthalten ist? Denn der HTTP Header fängt ja erst bei "POST..." an, oder?

                              Genau, IP ist verbindunglos und sorgt bei jedem Paket dafür, dass es am richtigen Rechner ankommt. Danach kommt der TCP-Header der die Portnummern enthält und erst dann kommen die Nutzdaten, in diesem Fall HTTP.

                              Ja, ich habe einfach beides versucht, und ich habe auch vorher in der  Doku gelesen, habe ss:// auch als erstes verucht, ging ja nicht, also habe ich mehr oder weniger aus Verzweiflung mal https:// probiert ;-) Aber ich habe das schon richtig verstanden, nur ein ssl:// davor und den SSL-Port und schon geht derselbe header über SSL, oder?

                              Ja genau. Bloß entweder ist das noch nicht fertig oder es muss beim Kompilieren extra eingeschaltet werden. Der kompilierte Snapshot scheint nur allgemeine OpenSSL-Funktionen zu enthalten.

                              Jetzt Frage ich mich wie man deises Beispiel auf 2 Servern verwenden kann, halt auf dem einen verschlüsseln, auf dem anderen entschlüsseln. Das ganze ist abgängig von 3 Variablen:

                              Der geheime Schlüssel ist in dem Beispiel very secret key. Den musst du unbedingt sicher von einem Rechner auf den anderen bringen, und der darf nicht öffentlich bekannt werden.

                              Wobei mir das Beispiel nicht wirklich gefällt, da da der Schlüssel aus einer MD5-Summe gemacht wird und die enthält leider (wie hier schon öfter zu lesen war) ein arg beschränktes Alphabet. Führ' lieber erstmal die ersten paar Zeilen aus und lass dir $ks ausgeben (ich tippe darauf, dass er 32 ausgeben wird) und besorg dir soviele zufällige Bytes. Die benutzt du dann als Schlüssel und weist sie an $key zu, auf der anderen Seite das gleiche.

                              Dann wäre da noch $iv, der Initialization Vector. Der wird bei jedem Verschlüsselungsvorgang zufällig erzeugt und den solltest du einfach so im Klartext ans andere Ende übertragen. $td ist bloss eine Ressource und muß also mit der angegebenen Funktion am anderen Ende neu erzeugt werden.

                              openssl muß ich gestehen verstehe ich nich nicht so recht wie ich das anwenden soll: http://www.php.net/manual/en/function.openssl-seal.php, da ist ja auch ein nettes Beispiel, da steht halt wie ich einen schlüssel erstelle, und dann free key, aber was sollte die ganze Aktion jetzt? Sende ich mit openssl die daten direkt wie mit fsockopen, und der SSL-Server erkennt das selbst und ich habe auf dem entgegennehmenden PHP-Script die Daten ganz normal zur Verefügung, doer muß ich auch hier den Datenstring verschlüsseln, was ja eigentlich reichen würde!

                              Für das OpenSSL-Gezeugs musst du dir erstmal ein Schlüsselpaar machen, wobei der Sender den öffentlichen Schlüssel bekommt und der Empfänger den privaten Schlüssel (der geheim bleiben muß). Beim Senden öffnest du dann den öffentlichen Schlüssel, nimmst openssl_seal() und schmeisst es auf den Schlüssel und den Klartext. Zurück kriegst du einen verschlüsselten Sitzungsschlüssel und den Geheimtext, die du beide an den Empfänger überträgst. Der öffnet seinen geheimen Schlüssel und schmeisst openssl_open() auf den Geheimtext, diesen Schlüssel und den verschlüsselten Sitzungsschlüssel und kriegt den Klartext zurück.

                              --
                              Henryk Plötz
                              Grüße von der Ostsee

                              1. Hi!

                                Naja, ich bezweifele das Du da was erkannt hättest,

                                Och, ich hätte RFC 791 und 793 gezückt und mich gefreut die mal auf einen Hexdump loslassen zu können.

                                Kann ich ja nicht ahnen das sowas geht ;-)

                                zumindest mein sniffer schreibt da grostes Kauderwelsch! "POST" ist das erste Wort was man lesen kann.

                                Nimm doch Ethereal.

                                Was denn jetzt, kannst du das im Klartext lesen oder nicht? Wenn nicht nehem ich auch kein Ethernal, das habe ich schonmal probiert und habe in 10 Minuten kein stück herausgefunden wie das blöde Ding funktioniert!

                                Leeider kann ich keien binärdaten lesen, oder was auch immer diese Kauderwelsch zu sagen hatte!

                                Das wären die IP und TCP-Header gewesen.

                                Und den Zeigt ethernal an? Oder mußt DU den erst durch ein eigenes Script schicken? Gibt´s eine PHP-Funktion die sowas entschlüsseln kann?

                                Ja genau. Bloß entweder ist das noch nicht fertig oder es muss beim Kompilieren extra eingeschaltet werden. Der kompilierte Snapshot scheint nur allgemeine OpenSSL-Funktionen zu enthalten.

                                Aber warum schreiben die das dann bei news.txt mit rein???

                                Die Sache mit mcrypt hat sich für mkich fürs erste erledigt, nicht nur das ich es bei  mir nicht ans laufen bekomme, auch mein Provider hat es nicht installiert! Also erstmal vergessen!(ich habe ihn trotzdem mal aufgefordert das Modul zu installieren :-))

                                Für das OpenSSL-Gezeugs musst du dir erstmal ein Schlüsselpaar machen, wobei der Sender den öffentlichen Schlüssel bekommt und der Empfänger den privaten Schlüssel (der geheim bleiben muß). Beim Senden öffnest du dann den öffentlichen Schlüssel, nimmst openssl_seal() und schmeisst es auf den Schlüssel und den Klartext. Zurück kriegst du einen verschlüsselten Sitzungsschlüssel und den Geheimtext, die du beide an den Empfänger überträgst. Der öffnet seinen geheimen Schlüssel und schmeisst openssl_open() auf den Geheimtext, diesen Schlüssel und den verschlüsselten Sitzungsschlüssel und kriegt den Klartext zurück.

                                OK. soweit in der Theorie. Soll also heißen das ich mich  um alles selbst kümmern muß, also dass keine SSL Verbindung einmal zu Stande kommt sondern das ich immer manuell bverschlüsseln muß, richtig? Wobei sich mir da die Frage stellt ob ich dann bei SSL bleibe, denn gerade bei openSSL ist ja die ein oder andere Sicherheitslücke bekannt, und wenn man das eh manuell macht, dann wäre vielleicht GPG doch die bessere Variante, oder?
                                Wobei ich jetzt SSL einmal hinbekommen möchte.
                                Mein erstes praktisches Problem, wie erstelle ich die Schlüssel? openssl_pkey_new () erzeugt also einen privaten schlüssel. Das mache ich dann mal auf beiden Servern und habe jeweils private schlüssel, die ich dann in einer Datei ablege, oder direkt im Script speichere. Dann gehen die Probleme los - wie komme ich an die öffentlichen Schlüssel? Hat das vielleicht was hiermit zu tun:
                                bool openssl_csr_new ( array dn, resource privkey [, array extraattribs [, array configargs]])

                                Also muß ich erstmal den privaten Schlüsselerzeugen, dann mit diesem privaten das den öffentlichen(csr(Zertifikat)), aber die Funktion gibt ja nur TRUE oder FALSE zurück, wie soll das bitte gehen? Und das wolll ich unter "dn" angeben?

                                Sagen wir mal ich hätte jetzt beide Schlüssel und würde die jeweils in einer Datei speichern. Dann baue ich aber ein Verbindung zum normalen HTTP-Server auf an Port 80? Nur stehe ich dann wieder vor dem Problem, der verschlüsselte String ist vermutlich binär, also muß ich das wieder wie bei gz als Datei-Upload tarnen oder was? Also dann den Sitzungsschlüssel als POST-Variable übertragen, und den ssl-String als weitere POST-Variable mit multipart/form-data und boundary...
                                Aber ich habe SSL immer anders begriffen. Ich dachte SSL sei eine Verschlüsselung auf euner niedrigeren Ebene als der Anwendungs-Ebene als HTTP, das also der komplette http-Traffic so verschlüsselt wird, ich also eine TCP/IP Verbindung zu Port 443 des SSL-Servers herstelle(mit Sitzungsschlüssel und private Key authentifizieren), die SSL-verschlüsselten Daten übertragen und mit den entsprechenden Schlüsseln den kompletten http-Header entschlüsseln und dann normal weiterverarbeiten.
                                Und ich habe ja einen Server der SSL spricht, der hat bestimmt auch ein Zertifikat... nur habe ich kei0en Ahnung wie ich das jetzt nutzen soll, so wie ich das verstehe ist das eine VErschlüsselung einer Post-Variable im HTTP-Header, das widersrpicht sich absolut mit meinem bisherigen Bild von SSL!

                                Dasselbe müßte dann irgendwie zurück funktionieren, aber ehrlich gesagt, ich habe mir jetzt einuges zu den PHP Funkionen bzgl. openssl durchgelsen, und das auch eínigermaßen verstanden, aber für mich sieht das _ganz_ anders aus als das was der Browser, cURL... unter SSL verstehen! Aber vermutlich habe ich es einfach noch nicht verstanden ;-)

                                Viele Grüße

                                Andreas

                                1. Moin,

                                  Kann ich ja nicht ahnen das sowas geht ;-)

                                  Naja, der Rechner muss doch auch irgendwie an die Informationen kommen, oder? Und da die wenigsten Computer über übersinnliche Fähigkeiten oder Intelligenz verfügen, müsste ein Mensch das doch allemal können.

                                  Was denn jetzt, kannst du das im Klartext lesen oder nicht? Wenn nicht nehem ich auch kein Ethernal, das habe ich schonmal probiert und habe in 10 Minuten kein stück herausgefunden wie das blöde Ding funktioniert!

                                  Also, du klickst auf Capture und suchst dir ein Interface aus (idealerweise das worüber die Daten gehen ;). Unter Windows heissen die alle so komisch, im Zweifelsfall probierst' halt alle durch. Dann lässt du ihn aufzeichnen und stoppst später die Aufzeichnung. Vor dir siehst du jetzt alle Pakete die im fraglichen Zeitraum an dir vorbeigezogen sind. Die kannst du dir jetzt einzeln ansehen und siehst unten in einer Baumansicht alle Header aufgeschlüsselt. Du kannst auch eines der Pakete einer TCP-Verbindung anklicken, rechts klicken und dann Follow TCP-stream auswählen, dann kriegst du die Nutzdaten der jeweiligen TCP-Verbindung (also zum Beispiel den HTTP-Dialog) in einem extra Fenster ohne das TCP/IP-Beiwerk dargestellt. Ausserdem wird ein Filter gesetzt, der nur noch Pakete dieser Verbindung anzeigt, den kannst du rechts unten mit Reset wieder ausschalten. Du kannst im Feld daneben auch eigene Filter eingeben, die Syntax ist (imho) perl-ähnlich: tcp.port eq 80 zeigt zum Beispiel nur TCP-Pakete an die von oder zu Port 80 (also HTTP) gegangen sind. Mehr Ausdrücke findest du in der Hilfe.

                                  Und den Zeigt ethernal an? Oder mußt DU den erst durch ein eigenes Script schicken?

                                  Ja, es zeigt sowohl die Binärdaten an, als auch die dekodierte Version. Wenn du etwas in der dekodierten Version markierst, markiert es sogar freundlicherweise die selbe Stelle in den Binärdaten.

                                  Gibt´s eine PHP-Funktion die sowas entschlüsseln kann?

                                  Noe, aber du kannst mit dem Wissen aus den RFCs 791, 793 und vielleicht noch 3168 eine Funktion schreiben.

                                  Aber warum schreiben die das dann bei news.txt mit rein???

                                  Es gibt Dinge zwischen Himmel und Erde...

                                  OK. soweit in der Theorie. Soll also heißen das ich mich  um alles selbst kümmern muß, also dass keine SSL Verbindung einmal zu Stande kommt sondern das ich immer manuell bverschlüsseln muß, richtig?

                                  Genau.

                                  Wobei sich mir da die Frage stellt ob ich dann bei SSL bleibe, denn gerade bei openSSL ist ja die ein oder andere Sicherheitslücke bekannt, und wenn man das eh manuell macht, dann wäre vielleicht GPG doch die bessere Variante, oder?

                                  Oehm, von einer OpenSSL-Sicherheitslücke (ausser den bekannten und längst korrigierten ;) weiss ich nichts. Du würdest auch auch gar kein OpenSSL benutzen, sondern nur den Verschlüsselungsteil davon (so wie mcrypt bloss anders). Aber GPG scheint mir doch die bessere Idee, ja.

                                  Du würdest dann einfach gpg -c benutzen, was aber unter Umständen auch wieder an popen()-Problemen krankt.

                                  Mein erstes praktisches Problem, wie erstelle ich die Schlüssel?

                                  Da die Funktionen nicht dokumentiert sind, kann ich dazu auch nicht allzuviel sagen.

                                  openssl_pkey_new () erzeugt also einen privaten schlüssel. Das mache ich dann mal auf beiden Servern und habe jeweils private schlüssel, die ich dann in einer Datei ablege, oder direkt im Script speichere.

                                  Du brauchst jeweils Privater Schlüssel/Öffentlicher Schlüssel für jede Richtung, ja.

                                  Dann gehen die Probleme los - wie komme ich an die öffentlichen Schlüssel? Hat das vielleicht was hiermit zu tun:
                                  bool openssl_csr_new ( array dn, resource privkey [, array extraattribs [, array configargs]])

                                  Eher nicht. Den Certificate Sign Request brauchst du nur, wenn du deinen öffentlichen Schlüssel von einer Certification Authority unterschreiben lassen willst.

                                  Da ich bei den PHP-Funktionen nichts dazu finde, könntest du dich direkt mal bei OpenSSL umsehen. Da ist ein kleines Kommandozeilentool bei, dass das Schlüsselerzeugen und Speichern können sollte.

                                  Sagen wir mal ich hätte jetzt beide Schlüssel und würde die jeweils in einer Datei speichern. Dann baue ich aber ein Verbindung zum normalen HTTP-Server auf an Port 80? Nur stehe ich dann wieder vor dem Problem, der verschlüsselte String ist vermutlich binär, also muß ich das wieder wie bei gz als Datei-Upload tarnen oder was? Also dann den Sitzungsschlüssel als POST-Variable übertragen, und den ssl-String als weitere POST-Variable mit multipart/form-data und boundary...

                                  Genau.

                                  Aber ich habe SSL immer anders begriffen. Ich dachte SSL sei eine Verschlüsselung auf euner niedrigeren Ebene als der Anwendungs-Ebene als HTTP, das also der komplette http-Traffic so verschlüsselt wird, ich also eine TCP/IP Verbindung zu Port 443 des SSL-Servers herstelle(mit Sitzungsschlüssel und private Key authentifizieren), die SSL-verschlüsselten Daten übertragen und mit den entsprechenden Schlüsseln den kompletten http-Header entschlüsseln und dann normal weiterverarbeiten.

                                  Ist es ja auch. Bloss die OpenSSL-Funktionen die zur Zeit da sind, implementieren nur einen kleinen Teil dessen was OpenSSL kann. Und das ist nunmal leider nur ein Teil des Teils der sich mit Schlüsseln und Verschlüsseln befasst. Eine SSL-Verbindung für HTTPS kannst du damit zur Zeit nicht bauen, dazu müsste wieder (wie bereits mehrfach erwähnt) das OpenSSL-Kommandozeilenprogramm mit Parameter s_client anrücken (popen()-Problem!).

                                  Das was du machen willst (Stream-Verbindung zu einem SSL-Server aufbauen) ist das was in den neuen Codeteilen implementiert wird (oder auch nicht *sigh*).

                                  --
                                  Henryk Plötz
                                  Grüße von der Ostsee

      2. Tag

        Aber ganz klappt es immer noch nicht:

        [_FILES] => Array
                (
                    [da_name] => Array
                        (
                            [name] => da_filename
                        )

        )

        da stimmt wohl was nicht ;-) Aber ich habe mich doch an die Vorgaben gehalten, oder?

        Auch wenn Du es jetzt schon geschafft hast, trotzdem nochmal der Hinweis: Ab PHP 4.2.0 existiert ein dicker Bug, der PHP bei Dateiuploads ab und zu (meistens aber öfter) alle oder einige Variablen aus $_POST vergessen lässt.
        Nur, damit Du Dich nicht wunderst, wenn's bei Dir funzt und woanders dann nicht ;)

        Ciao,

        Harry

        1. Grmbl

          Auch wenn Du es jetzt schon geschafft hast, trotzdem nochmal der Hinweis: Ab PHP 4.2.0 existiert ein dicker Bug, der PHP bei Dateiuploads ab und zu (meistens aber öfter) alle oder einige Variablen aus $_POST vergessen lässt.

          Wollte ich noch einen Link dazu angeben ?
          Ich glaube schon.
          Aber warum fällt mir das immer erst danach ein ?

          http://bugs.php.net/bug.php?id=17958

          Ciao,

          Harry

          1. Hi!

            http://bugs.php.net/bug.php?id=17958

            Vielen Dank! Interssante Sache. Aber da geht es wohl um $_POST, die brauche ich (zur Zeit) nicht, bis jetzt verwende ich nur $_FILES. Wobei einige Leute ja auch davon sprachen das binäre Daten zerstört wurden. Zum Glück verwende ich auf dem Remote-Server noch PHP 4.1.2 ;-)
            Das ganze scheint ja auch irgendwie Client-abhängig zu sein, und auch abhängig vom Parser, vielleicht hat das was auch damit zu tun das die binären Daten von cURL nicht korrekt ankamen? Vielleicht hat es in 4.1.2 ja damit angefangen ;-)

            Danke Dir für den Hinweis!

            Grüße
            Andreas

            1. Tach

              Das ganze scheint ja auch irgendwie Client-abhängig zu sein, und auch abhängig vom Parser, vielleicht hat das was auch damit zu tun das die binären Daten von cURL nicht korrekt ankamen? Vielleicht hat es in 4.1.2 ja damit angefangen ;-)

              Ne, angefangen hat es erst in PHP 4.2.0. Das "tolle" an PHP 4.2.0 war ja die komplett neu geschriebene Routing zur Behandlung von post-Requests ... naja, man sieht ja, was dabei rausgekommen ist: Ein Haufen Sicherheitslücken und ein richtig dicker Bug, um den sich keine Sau so richtig kümmert. Da könnte man echt nen Hass kriegen, so ein dickes Ding, und schon über zwei Monate alt *grrrr*

              Ciao,

              Harry