[PATCH] - HttpUtils - Support von HTTP Digest Authentifizierung

Begonnen von Markus Bloch, 26 Oktober 2015, 21:06:30

Vorheriges Thema - Nächstes Thema

Markus Bloch

Hallo zusammen,

anbei ein Patch für HttpUtils um Digest-Authentifizierung zu unterstützen. Ich habe eine IP-Kamera, die keine Basic-Authentifizierung akzeptiert sondern nur Digest. Daher habe ich Digest nach RFC2069 & RFC2617 implementiert.

Dazu ist es notwendig die Antwort mit der Challenge zu empfangen und dann den Request samt Challenge-Response erneut zu schicken.  Dieses Schema habe ich auch für die Basic-Authentifizierung analog umgesetzt, damit nicht Passwörter einfach auf Dumm immer mitgesendet werden die dann jeder mit etwas Know-How einsehen kann. Der Server sagt nun, was er haben will (Basic/Digest) und der Request wird dann erneut mit der gewünschten Methode abgesetzt. Da kann man jetzt drüber streiten ob das gut ist oder sinnlose Zeit/Performance frisst.

Das Ergebnis wurde gegen einen eigenen Apache getestet (mit und ohne "qop"-Parameter), sowie gegen http://httpbin.org/ (funktioniert nur, wenn ein Cookie "fake=fake_value" mit gesendet wird)

Im Anhang gibt es einmal ein Diff, sowie eine volle HttpUtils.pm. Basic Authentifizierung funktioniert ebenfalls.

Viele Grüße

Markus
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

rudolfkoenig

Nach diesen Aenderungen wird bei gesetzten Benutzername/Passwort der erste Request ohne Authorization: im Header geschickt, damit es an der Antwort des Servers die gewuenschte Authorisierungsmethode (basic oder digest) rausgefunden werden kann.

Das fuehrt zur Verdoppelung des bisherigen Aufwandes bzw. Laufzeit bei Requests mit Basic-Auth. Normalerweise weiss mann, welche Authentifizierung gewuenscht wird, deswegen ist mir das zu teuer.

Um den Code lesbar zu halten, schlage ich vor diese Behandlung in einer separaten Funktion zu implementieren.

Markus Bloch

Zitat von: rudolfkoenig am 27 Oktober 2015, 09:39:06
Nach diesen Aenderungen wird bei gesetzten Benutzername/Passwort der erste Request ohne Authorization: im Header geschickt, damit es an der Antwort des Servers die gewuenschte Authorisierungsmethode (basic oder digest) rausgefunden werden kann.

Das fuehrt zur Verdoppelung des bisherigen Aufwandes bzw. Laufzeit bei Requests mit Basic-Auth. Normalerweise weiss mann, welche Authentifizierung gewuenscht wird, deswegen ist mir das zu teuer.
Bei Digest muss man die Antwort des Servers abwarten um die Challenge-Daten zu erhalten. Da führt kein Weg dran vorbei.

Bei Basic geht es mir darum nicht gleich das Passwort auf den Präsentierteller zu legen.

Ob Digest oder Basic notwendig ist, wissen wir als Entwickler durchaus, aber ein normalsterblicher User in der Regel nicht. Der weis nur: "ich brauch ein Username/Passwort um die URL aufzurufen".

Alternativ würde ich sonst vorschlagen bei gesetzten User/Passwd den Basic-Header sofort im Request zu schicken. Sollte der Server ein 401 mit Digest-Challenge senden, dann den Request mit Challenge-Response erneut zu schicken.

Zitat von: rudolfkoenig am 27 Oktober 2015, 09:39:06
Um den Code lesbar zu halten, schlage ich vor diese Behandlung in einer separaten Funktion zu implementieren.

OK, ich werde den Patch nochmal entsprechend ändern.
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

Markus Bloch

#3
Anbei der Patch mit folgenden Anpassungen:

- Basic wird wieder mitgesendet (wie bisher auch)
- Sollte der Server Digest verlangen, wird der Header durch HttpUtils_DigestHeader() generiert und in $hash->{header} gesetzt/angehangen und neu abgesetzt
- Sollte dennoch ein 401 kommen, wird die Fehlermeldung "wrong authentication" zurückgemeldet.

Getestet mit Basic, Digest ohne qop sowie Digest mit qop und keine Authentifizierung.

Viele Grüße

Markus
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

rudolfkoenig


fhainz

Hallo!

Anscheinend gibt es mit dem Patch ein Problem mit dem Pushbullet Modul (klick). Nach dem Aufruf bekomme ich diese Fehlermeldung.

POST requests require a <code>Content-length</code> header.

Global verbose 5

2015.10.29 19:57:11.204 5: Cmd: >set pushbullet message fsa<
2015.10.29 19:57:11.205 4: HttpUtils url=https://APIKEY: @api.pushbullet.com/v2/pushes
2015.10.29 19:57:11.406 4: https://APIKEY: @api.pushbullet.com/v2/pushes: HTTP response code 411
2015.10.29 19:57:11.406 4: HttpUtils https://APIKEY: @api.pushbullet.com/v2/pushes: Got data, length: 1564
2015.10.29 19:57:11.406 3: Something gone wrong
2015.10.29 19:57:11.406 5: Triggering pushbullet (1 changes)


Der Aufruf sieht so aus:

$json = JSON->new->latin1->encode($jsonHash) if( $jsonHash );
   
  ($err,$data)    = HttpUtils_BlockingGet({
    url           => $url,
    method        => $method,
    header        => "Content-Type: application/json",
    data          => $json
  });
 


Ich kann mir das nicht so richtig erklären. Die content-lenght wird doch durch die HttpUtils gesetzt.
Jemand eine Idee?

Grüße

betateilchen

-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

rudolfkoenig

Da offensichtlich Probleme gibt, ich sie aber weder reproduzieren kann, noch eine Idee habe wie ich sie fixen soll, und Digest nur von Markus verwendet wird, habe ich den Patch entfernt, und wieder die alte Version fuers update zur Verfuegung gestellt.

Es waere wichtig eine einfache Testmethode zur Verfuegung zu stellen, damit wir das Problem reproduzieren und fixen koennen.

Markus Bloch

@fhainz: Kann ich dir eine Version von HttpUtils.pm mit Digest-Implementierung und ein paar zusätzlichen Logausgaben geben, damit wir dem Problem auf die Spur kommen können?

Vielen Dank

Gruß
Markus
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

fhainz


Markus Bloch

Hallo zusammen,

anbei eine Version von HttpUtils mit meiner Digest-implementierung sowie mit Logausgaben was an HTTP Daten gesendet und empfangen wurde.

Es wäre toll, wenn ihr diese mal ausprobieren könnt, mit den Geräten/URL's die nicht funktionieren. Damit ich sehen kann, wieso und weshalb.

Bitte darauf achten, dass in Zeilen mit "Authorization: Basic [XXX]" das [XXX] unkenntlich gemacht ist, da sich dahinter der Username+Passwort in BASE64 verbirgt, welches sich entschlüsseln lässt.

Vielen Dank

Gruß
Markus
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

fhainz

Hallo!

Hier die Logs

2015.11.01 19:05:45.841 3: HttpUtils sent: POST /1/users/validate.json HTTP/1.0
Host: api.pushover.net
User-Agent: fhem
Content-Length: 72
Content-Type: application/x-www-form-urlencoded
2015.11.01 19:05:46.363 3: HttpUtils received: HTTP/1.1 200 OK
Date: Sun, 01 Nov 2015 18:05:46 GMT
Content-Type: application/json; charset=utf-8
Connection: close
Status: 200 OK
X-UA-Compatible: IE=Edge,chrome=1
ETag: "dd288bf11d7eaab2f9d198cd66e9e5dd"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: 2c5a0ce7381a82ced16408f7daefc384
X-Runtime: 0.009382
X-Frame-Options: DENY
Strict-Transport-Security: max-age=31536000

{"status":1,"group":0,"devices":["iPad","iPhone"],"request":"2c5a0ce7381a82ced16408f7daefc384"}
2015.11.01 19:06:06.795 3: HttpUtils sent: POST /v2/pushes HTTP/1.0
Host: api.pushbullet.com
User-Agent: fhem
Authorization: Basic [XXX]

Content-Type: application/json
Content-Length: 61

2015.11.01 19:06:06.842 3: HttpUtils received: HTTP/1.0 411 Length Required
Content-Type: text/html; charset=UTF-8
Content-Length: 1564
Date: Sun, 01 Nov 2015 18:06:06 GMT
Server: GFE/2.0

<!DOCTYPE html>
<html lang=en>
  <meta charset=utf-8>
  <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
  <title>Error 411 (Length Required)!!1</title>
  <style>
    *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
  </style>
  <a href=//www.google.com/><span id=logo aria-label=Google></span></a>
  <p><b>411.</b> <ins>That's an error.</ins>
  <p>POST requests require a <code>Content-length</code> header.  <ins>That's all we know.</ins>



Grüße

Markus Bloch

Vielen Dank. Fehler gefunden.

Grund war der Aufruf von encode_base64. Ich hatte den zweiten Parameter nicht gesetzt, so wie es bisher auch war. Bei meinem Perl scheint hier "" Standard zu sein, bei anderen ist es "\n"

alt:
  $hdr .= "Authorization: Basic ".encode_base64($hash->{auth})."\r\n"

neu:
  $hdr .= "Authorization: Basic ".encode_base64($hash->{auth}, "")."\r\n"

Anbei der korrigierte Patch.

Gruß
Markus
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

fhainz


rudolfkoenig

Habe den Patch ohne Aenderungen uebernommen und eingecheckt.