Programmierung > Delphi/Lazarus > FRITZ!Box

Anmeldung mit SessionID

FRITZ!OS 5.50 (Firmware xx.05.50 - Klasse ab v0.16)

Mit dem FRITZ!OS 5.50 (Firmware xx.05.50) hat AVM die Anmeldung mit SessionID geändert. Dies war notwendig weil Benutzerkonten angelegt werden können.

Boxinfo

Eigenschaften

Es stehen folgende Eigenschaften zur Verfügung:

property IsLoggedIn: Boolean;
property LogIn: Boolean;
property LogOut: Boolean;
property Username: String;
property Password: String;
property Session: TSession;

OUT IsLoggedIn: Nach Überprüfung der Sessiondaten erhält man die Information, ob die Anwendung an der FRITZ!Box angemeldet ist.

OUT LogIn: Es wird versucht, die Anwendung an der FRITZ!Box anzumelden. Als Ergebnis wird zurückgegeben, ob die Anwendung angemeldet ist.

OUT LogOut: Es wird versucht, die Anwendung von der FRITZ!Box abzumelden. Als Ergebnis wird zurückgegeben, ob die Anwendung noch angemeldet ist.

IN Username: Der Name des Benutzers, welcher angemeldet werden soll. Der Name kann leer bleiben wenn keine Benutzerkonten angelegt wurden.

IN Password: Das Passwort des Benutzers.

OUT Session: Es werden die Sessiondaten zurückgegeben. Dies ist ein Record mit den Daten SID, Challenge und Rights. Rights ist ein Array aus Records mit den Daten Name und Access

SID ist die 64 Bit lange SessionID. Wenn die Anwendung nicht angemeldet ist, ist diese ungültig und hat in der Regel den Wert 0000000000000000. Challenge ist ein String, welcher für die Verschlüsselung des Passwortes benötigt wird. Rights enthält eine Liste von Benutzerkonten. Name gibt den Benutzernamen und Access die Berechtigungen des Benutzers an. 0 - kein Zugriff, 1 - lesender Zugriff und 2 - schreibender Zugriff.

Anwendung

Beispiel für die Anwendung der Eigenschaften

procedure TfrmMain.sbnLoginLogoutClick(Sender: TObject);
var
  aLoggedIn : Boolean;
  aSession  : TSession;
begin
  {
  *  An- bzw Abmelden.
  }
  if fFritzBox.IsLoggedIn
  then begin
    aLoggedIn := fFritzBox.LogOut;
  end
  else begin
    fFritzBox.Username := edtUsername.Text;
    fFritzBox.Password := edtPassword.Text;
    aLoggedIn := fFritzBox.LogIn;
  end;
  {
  *  Kontrolllampe einstellen.
  }
  imgRed.Visible   := not(aLoggedIn);
  imgGreen.Visible := aLoggedIn;
  {
  *  Sessiondaten holen und anzeigen.
  }
  aSession := FFritzbox.Session;
  lblSessionIDValue.Caption        := aSession.SID;
  lblSessionChallengeValue.Caption := aSession.Challenge;
end;

edtUsername und edtPassword enthalten in der Demo den Benutzernamen und dessen Passwort für die Fritzbox. imgRed und imgGreen sind zwei übereinander liegende TImages, welche als Kontrollanzeige fungieren. lblSessionIDValue und lblSessionChallengeValue sind TLabel zur Anzeige der Sessiondaten.

Informationen

Die SessionID wird über das Lua-Script login_sid.lua abgefragt, welches über einen Winsock-Client als HTTP-Request aufgerufen wird:

GET /login_sid.lua?sid=0000000000000000 HTTP/1.1
Host: fritz.box:80
Accept: text/xml
Keep-Alive: 115
Connection: Keep-Alive

Die SessionID muss hier nicht zwingend angegeben werden.

Die Antwort sieht zum Beispiel so aus:

HTTP/1.1 200 OK
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/xml
Keep-Alive: timeout=60, max=300
 
a5
<?xml version="1.0" encoding="utf-8"?>
<SessionInfo>
  <SID>0000000000000000</SID>
  <Challenge>9315f027</Challenge>
  <BlockTime>0</BlockTime>
  <Rights></Rights>
</SessionInfo>
 
0

Ob man an der Fritzbox angemeldet ist, kann man an der SID und dem Inhalt von Rights erkennen. Hier hat die SID den Wert 0000000000000000 und Rights ist leer. Die Anwendung ist also nicht angemeldet. Der Wert von Challenge wird für die Verschlüsselung des Passwortes benötigt.

Auch hier wird aus dem Wert für Challenge und dem Passwort ein Response-Wert ermittelt. Der Wert von Challenge wird über einen Bindestrich mit dem Passwort verbunden. Dieser String muss als UTF16LE-String vorliegen. Dabei müssten Zeichen mit einem Unicode Codepoint über 255 aus Kompatibilitätsgründen mit dem Zeichen "." (UTF16LE: $2e00) ersetzt werden, was die Komponente jedoch nicht berücksichtigt. Zu diesem UTF16LE-String wird ein MD5Hash ermittelt. Dieser MD5Hash wird wiederum mit einem Bindestrich an die Challenge angehängt.

aLoginResponse := fSession.Challenge + '-' +
                  MD5Hash(AnsiToUtf16(fSession.Challenge + '-' + fPassword));

Der aLoginResponse und der Benutzername bilden die Parameter für das Lua-Script:

aParams := Format('&username=%s&response=%s', [fUsername, aLoginResponse]);

Da in der Komponente Lua-Scripte immer mit SID aufgerufen werden, beginnt der Parameterstring mit einem &. Sonst würde dort ein ? stehen.

Die Anmeldung erfolgt mit dem wiederum mit dem Lua-Script:

GET /login_sid.lua?sid=0000000000000000&username=
                     &response=e2cbc12f-c9aa5cb6d1a2be3acebea16b5e2f61b9 HTTP/1.1
Host: fritz.box:80
Accept: text/xml
Keep-Alive: 115
Connection: Keep-Alive

Die ersten beiden Zeilen sind eine Zeile und wurden hier wegen der Länge getrennt. Die mögliche Antwort sieht so aus:

HTTP/1.1 200 OK
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/xml
Keep-Alive: timeout=60, max=300
 
<?xml version="1.0" encoding="utf-8"?>
<SessionInfo>
  <SID>6a54ae7eb7b87185</SID>
  <Challenge>b33b613e</Challenge>
  <BlockTime>0</BlockTime>
  <Rights>
    <Name>Dial</Name>
    <Access>2</Access>
    <Name>HomeAuto</Name>
    <Access>2</Access>
    <Name>BoxAdmin</Name>
    <Access>2</Access>
    <Name>Phone</Name>
    <Access>2</Access>
    <Name>NAS</Name>
    <Access>2</Access>
  </Rights>
</SessionInfo>

An der SID und der Liste unter Rights kann man sehen, dass das Einloggen erfolgreich war.

Links

Technical Note zum geänderten Login-Verfahren