Content tagged DE

Meine Zertifikate: 汉语水平考试(HSK)一级和二级

posted on

Inzwischen steht mein Kopf eher schon beim nächsten Test. Trotzdem wollte ich noch von meinen Prüfungen im September abschließend berichten:

Mein Gefühl hat sich bestätigt, ich habe beide Prüfungen bestanden. HSK1 sogar ohne Fehler. Die Ergebnisse waren ab dem 16. Oktober online einsehbar. Hierzu kann man sich einfach mit den persönlichen Zugangsdaten auf der Seite anmelden über die der Test auch gebucht wurde und sieht dann die Ergebnisse oder man kann auch ohne Login dort die Ergebnisse abfragen, wenn man seinen Namen und die Admission-Ticket-Nummer eingibt. Am 9. November war es dann soweit und ich konnte auch meine Zertifikate im Konfuzius Institut München abholen.

汉语水平考试(HSK)一级和二级

posted on

Letzten Sonntag habe ich mein Chinesisch testen lassen. Ich hatte mich zu den Prüfungen HSK 1 und HSK 2 angemeldet. Ursprünglich wollte ich nur die niedrigste Stufe HSK 1 schreiben und meldete mich entsprechend an. In der Vorbereitung merkte ich jedoch schnell, dass die Anforderungen hierfür nicht so hoch waren wie ich dachte. Zwar gab es noch ein paar Vokabeln, die ich nicht kannte, aber im Großen und Ganzen hatten wir den Stoff längst im Unterricht behandelt.

Dann laß ich beim Konfuzius Institus München, dass es auch möglich ist sich für zwei benachbarte Prüfungslevel gleichzeitig anzumelden. Die Prüfungszeiten sind so geplant, dass dies geht. Das klang gut: für HSK 1 konnte ich mich eh nicht mehr abmelden und ich könnte parallel versuchen, ob ich nicht schon die nächste Stufe schaffe. Gedacht getan, ich meldete mich auch hierfür an.

Meine Vorbereitung habe ich entsprechend auf die 300 Wörter/Zeichen des HSK 2 ausgedehnt und mich mit der erweiterten Gramatik beschäftigt. Ich fühlte mich bis zum Tag davor recht gut vorbereitet. Dann allerdings machte ich Probeaufgaben zum HSK 2 und war nicht mehr ganz so sicher. Die Sprache in den Höraufgaben war doch deutlich schneller als ich es gewohnt war. Die Beispiele in den Textaufgaben teilweise schwer verständlich für mich. Nach der Auswertung der Probeaufgaben dachte ich: okay, es könnte doch knapp werden.

Sonntag begann mein Prüfungstag zuerst mit HSK 2 um 10:00 Uhr, Prüfungsdauer etwa eine Stunde. In der Prüfung kam dann schnell das gute Gefühl zurück. Die Audiotexte waren langsamer und besser verständlich als das was ich von den Probeaufgaben kannte. Bei den meisten Aufgaben bin ich ziemlich sicher, dass ich sie richtig gelöst habe. Die Antwort ist fast immer eine Multiple-Choice-Auswahl und die falschen Möglichkeiten waren meist eindeutig falsch – mir schienen keine Gemeinheiten eingebaut. Auch die Textaufgaben habe ich ganz gut verstanden.

Am Nachmittag stand dann noch HSK 1 an. Diese Prüfung dauert nur etwa eine Dreiviertelstunde. Nach der guten Erfahrung im schwereren Niveau hatte ich keine Sorgen vor dieser Prüfung. So war es dann auch: Ich habe diese wirklich als sehr einfach empfunden. Ich hätte mich wohl geärgert, wenn ich nicht auch an HSK 2 versucht hätte. Jetzt muss ich etwa einen Monat warten, dann kann ich meine Ergebnisse abrufen.

Benutzt du Clojure in der Arbeit?

posted on

Wenn ich auf ein Meetup gehe, lautet die erste Frage immer „was machst du so?“. Beginnt das typische Gespräch hingegen mit „benutzt du Clojure in der Arbeit?”, bin ich auf der :clojureD in Berlin gelandet.

Am 24. Februar war ich auf meiner ersten Clojure-Konferenz. Nach einem Treffen der Munich Clojurians war das erst mein zweites Zusammentreffen mit anderen, die der Begeisterung dieser Programmiersprache erlegen sind.

Es war ein tolles Erlebnis. Auf keiner Konferenz bisher hatte ich so den Eindruck, dass alle einfach ein rießen Interesse an Softwareentwicklung haben und alle dafür brennen neue Gedankenanstöße aufzunehmen. Keiner der einfach nur seine Arbeit erledigt bekommen will. Ich hatte das Gefühl wirklich unter den Besten zu sein, die es in meinem Beruf gibt.

Wie schade, dass anscheinend trotzdem das Potential der Sprache so oft noch nicht genutzt wird. Obwohl ich im Cognicast oft genug auch schon die andere Seite gehört habe: Firmen, die darüber klagen zu wenige Clojure-Entwickler zu finden. Die Antwort auf der :clojureD war leider öfters: „nein, in der Arbeit nutze ich kein Clojure“.

VDSL von der Telekom mit IPv6 und Debian

posted on

IPv6 is the new normal

Meine letzten IPv6-Tunnel werden langsam überflüssig. Seit letzter Woche haben wir auch im Büro natives IPv6. Die Telekom hat uns auf einen NGN-Anschluss umgestellt.

Setup

IPv6 aktivieren

Kurz zusammengefasst

Für den IPv6-Zugang muss der pppd IPv6 auf der PPP-Verbindung aktivieren. Die Telekom benutzt dann Router-Advertisements (radv) um dem ppp0-Device eine IPv6-Adresse zu geben. Soll IPv6 im LAN weiterverteilt werden, bekommen wir Präfixe hierfür über Präfix-Delegation per DHCPv6. Letzteres kann aber nicht als Ersatz für die Router-Advertisements genutzt werden, da die Telekom nur Präfixdelegation darüber macht.

pppd konfigurieren

Nachdem der IPv4-Internetzugang konfiguriert ist muss nur noch IPv6 im pppd aktiviert werden. Hierzu muss an das Ende von /etc/ppp/options eine Zeile +ipv6 eingefügt werden.

echo "+ipv6" >> /etc/ppp/options

poff
pon dsl-provider

Das ppp0-Device sollte jetzt eine link local IPv6-Adresse haben (fe80:…). Wir können das mit ifconfig ppp0 kontrollieren.

IPv6-Adresse per Router Advertisement (radv) erhalten

Wir benutzen das Linux-System als Router. Wenn wir das Routing von IPv6-Traffic einschalten bezieht Linux seine IPv6-Adressen normalerweise nicht mehr automatisch. Über den Config-Wert 2 für die Einstellung accept_ra lässt sich dies jedoch überschreiben:

echo net.ipv6.conf.all.forwarding = 1 > /etc/sysctl.d/01-ipv6-forward.conf
echo net.ipv6.conf.ppp0.accept_ra = 2 >> /etc/sysctl.d/01-ipv6-forward.conf

echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
echo 2 > /proc/sys/net/ipv6/conf/ppp0/accept_ra

Wir müssen jetzt gegebenfalls auf das nächste Router Advertisement der Telekom warten. Dies kommt nur alle fünf Minuten. Haben wir diese Gedult nicht, können wir mit poff und pon dsl-provider uns nochmals neu einwählen. Danach sollte unser Interface ppp0 auch eine öffentliche IPv6-Adresse haben (2003:…).

Präfixe für die Subnetzs von DHCPv6

Als DHCPv6-Client habe ich dibbler-client und wide-dhcpv6-client ausprobiert letzterer war in der Lage deutlich schneller zu starten und zu stoppen, so dass ich mich für die WIDE-Implementierung des DHCPv6-Clients entschieden habe:

apt update
apt install wide-dhcpv6-client

Folgende Konfiguration habe ich als /etc/wide-dhcpv6/dhcp6c.conf angelegt:

interface ppp0 {
        send ia-pd 0;
};

id-assoc pd 0 {
        prefix-interface eth1 {
                sla-len 8;
                sla-id 1;
        };
        prefix-interface eth2 {
                sla-len 8;
                sla-id 2;
        };
};

Mit dieser Konfiguration wird ein Präfix über das Interface ppp0 vom DHCPv6-Server der Telekom angefordert. Dieses Präfix wird dann benutzt um Subnetze für eth1 und eth2 abzuleiten. Hierzu wird das von der Telekom erhaltene Präfix um 0001 verlängert für eth1 (sla-id 1) und entsprechend um 0002 für eth2.

Abschließend muss der wide-dhcpv6-client noch über die Datei /etc/default/wide-dhcpv6-client für das Interface ppp0 aktiviert werden:

# Defaults for dhcpv6 client initscript
# Used by /etc/init.d/wide-dhcpv6-client

# Interfaces on which the client should send DHCPv6 requests and listen to
# answers. If empty, the client is deactivated.
INTERFACES="ppp0"
service wide-dhcpv6-client restart

Jetzt sollten auch unsere Netzwerkinterfaces eth1 und eth2 IPv6-Adressen (und zugehörige Subnetze /64) erhalten haben.

Den Rechnern im LAN eine IPv6-Adresse zuweisen

(Genauer: Den Rechnern im LAN ihr Präfix mitteilen, so dass diese sich eine IPv6-Adresse geben können.)

Wir müssen auf dem Linux-Router hierzu selbst Router Advertisements auf unseren LANs verschicken. Dies geschieht mit dem Router Advertisement Daemon radvd:

apt install radvd

Für diesen Dämon legen wir die Konfigurationsdatei /etc/radvd.conf an:

interface eth1
{
        AdvSendAdvert on;
        prefix ::/64
        {
                AdvOnLink on;
                AdvAutonomous on;
                AdvRouterAddr on;
        };

        RDNSS 2001:4860:4860::8888  2001:4860:4860::8844
        {
        };
};

interface eth2
{
        AdvSendAdvert on;
        prefix ::/64
        {
                AdvOnLink on;
                AdvAutonomous on;
                AdvRouterAddr on;
        };

        RDNSS 2001:4860:4860::8888  2001:4860:4860::8844
        {
        };
};

Das Präfix ::/64 in dieser Konfiguration ist ein spezieller Wert. Der radvd benutzt für die Advertisements die auf dem jeweiligen Interface konfigurierten IPv6-Adressen um den Präfix selbst zu erreichnen. Die IPv6-Adresse hat uns im vorherigen Schritt der DHCPv6-Client automatisch gesetzt.

Der radvd muss noch mit der neuen Konfiguration aktiviert werden:

service radvd restart

Rechner im LAN vor eingehenden Verbindungen schützen (optional)

Wer es wirklich will und NAT bisher als Schutz seiner Rechner angesehen hat, kann über ip6tables noch einrichten, dass auch über IPv6 nur Verbindungen vom LAN ins Internet aufgebaut werden. TCP-Verbindungen aus dem Internet ins LAN werden damit abgewiesen. Hier die Datei /etc/init.d/ipv6-firewall anlegen:

#!/bin/sh
# kFreeBSD do not accept scripts as interpreters, using #!/bin/sh and sourcing.
if [ true != "$INIT_D_SCRIPT_SOURCED" ] ; then
    set "$0" "$@"; INIT_D_SCRIPT_SOURCED=true . /lib/init/init-d-script
fi
### BEGIN INIT INFO
# Provides:          ipv6-firewall
# Required-Start:    $network $remote_fs $syslog
# Required-Stop:     $network $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Starting IPv6 firewall
# Description:       This are some firewalling rules for our
#                    IPv6 connection to the internet.
### END INIT INFO

DESC="Starting IPv6 firewall"


case "$1" in
  start)
     /sbin/ip6tables -A FORWARD -m state --state NEW -i eth1 -o ppp0 -j ACCEPT
     /sbin/ip6tables -A FORWARD -m state --state NEW -i eth2 -o ppp0 -j ACCEPT
     /sbin/ip6tables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
     /sbin/ip6tables -A FORWARD -p tcp -j REJECT

     /sbin/ip6tables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
     /sbin/ip6tables -A INPUT -p tcp -j REJECT
     ;;
  stop)
     /sbin/ip6tables -F INPUT
     /sbin/ip6tables -F OUTPUT
     /sbin/ip6tables -F FORWARD
     ;;
  force-reload|restart)
     $0 stop
     $0 start
     ;;
  *)
     echo "Usage: /etc/init.d/ipv6-firewall {start|stop|restart}"
     exit 1
esac

exit 0

Dieses Skript installieren und aktivieren:

update-rc.d ipv6-firewall enable
service ipv6-firewall start

Das war's … die lokalen Netze haben jetzt IPv6-Zugang.

Worin ich mich 2016 verbessere: Clojure und Softwaretests

posted on

Mein einer Vorsatz für dieses Jahr ist es die Philosophie von Clojure zu denken. Seit 2011 spiele ich mit Lisp und 2014 hatte ich meinen ersten Kontakt zu Clojure, einem der Dialekte von Lisp. Der andere ist, ich möchte meine Erfahrungen mit Softwaretests ausbauen. Bisher hatte ich vor allem an meinen Fähigkeiten mit Unit-Tests gearbeitet und hierfür meinen Stil gefunden. Jetzt will ich automatische Integrationstests in mein Standardrepertoire von Entwicklungstechniken aufnehmen.

Jetzt im Mai?

Du kennst es bestimmt: an Silvester hast du gute Vorsätze für das neue Jahr und ab Neujahr ist es schwer diese einzuhalten. Die letzten Jahre bin ich gut damit gefahren mir nichts konkretes vorzunehmen, stattdessen ist mein Ziel etwas neues zu erreichen. Das heißt Anfang des Jahres bin ich noch auf der Suche was in diesem Moment das richtige für mich ist. Ich probiere verschiedene Dinge und experimentiere damit. Merke ich, dass es nicht das richtige ist, so muss ich nicht mit meinem Vorsatz brechen, sondern mache mich auf die Suche nach etwas anderem.

Für dieses Jahr bin mir inzwischen sicher, dass ein großes Thema für mich ist, dass ich in den beiden genannten Gebieten mehr Erfahrung sammeln will.

Lisp/Clojure

Web Deelopment with Clojure

Funktionale Programmierung fasziniert mich seitdem ich im ersten Semester an der TUM davon gehört habe. Auch wenn mein täglicher Berufsalltag objektorientiert ist, schreibe ich in diesem Rahmen funktional: Seiteneffekte wo nicht nötig vermeiden, bevorzugt verwende ich unveränderliche Value-Objekte und genieße wie ich in Java8 mit Streams ausdrücken kann was ich mit Daten machen möchte und nicht sagen muss, wie das geschehen soll.

Zu kämpfen habe ich noch damit herauszufinden wie ich ohne Klassen meine Programme auf höherer Ebene möglichst sauber strukturiere. Ich merke den Vorsprung, den die objektorientierte Denkweise in meinem Kopf hat: was ich in Java schreibe hat einfach noch die schönere Globalstruktur, es gelingt mir besser zusammen zu halten was zusammen gehört („high cohesion“) und getrennte Konzepte getrennt zu halten („loose coupling“). Ich denke, es liegt daran, dass ich schon deutlich mehr gute Beispiele für OOP als für funktionale Programme gesehen habe.

Clojure Applied

Vorwärts gebracht haben mich hier dieses Jahr bisher vorallem die Bücher Web Development with Clojure von Dmitri Sotnikov und Michael Swaine am Beispiel von Webanwendungen und Clojure Applied von Alex Miller und Ben Vandgrift für allgemeine Clojure-Programme. Nun muss ich in der Praxis probieren was ich gelesen habe. Hierzu schreibe ich ein Tool das ich brauche gerade als Clojure-Webanwendung. Mal schauen wie ich mit dem Ergebnis zufrieden sein werde …

Service- und Akzeptanztests

Nachdem ich meine Muster für Unittests mit jUnit, Hamcrest und Mockito gefunden habe arbeite ich jetzt daran die richtigen Werkzeuge und Muster für Tests auf höherer Ebene zu finden. Schon vor einiger Zeit hatte ich mit Fit einige Versuche unternommen. Inzwischen ist dieses Werkzeug Teil von FitNesse geworden. Tests werden hierbei in HTML-Dateien geschrieben. Diese können wahlweise zum Beispiel auch in Word oder einem Wiki erstellt werden. „Richtig“ fühlt sich das für mich bisher aber nicht an. Seit ein paar Monaten experimentiere ich stattdessen mit Cucumber. Die Tests werden dabei in (einigermaßen) natürlicher Sprache geschrieben und in einem Textdokument abgelegt. Für mich als Entwickler fühlt sich das sehr viel besser an.

In Fit wird damit argumentiert, dass ein Kunde/Auftraggeber besser in der Lage sei eine Spezifikation zu editieren, wenn er dies in seiner gewohnten Textverarbeitung tun kann. Ich denke aber, dass es immer ein Wunsch bleiben wird, dass man als Entwicklungsteam eine fertige Spezifikation erhält. Es ist wichtiger ein Tool in der Hand zu haben, das es mir ermöglicht mit dem Kunden/Auftraggeber zusammen dies zu erarbeiten. Das ist aber genauso in einem Texteditor möglich. Wichtig ist vielmehr, dass der Kunde ein Verständnis dafür hat, was niedergeschrieben wird. Hierfür eigent sich Gherkin, die Sprache von Cucumber, ausgezeichnet: die Spezifikation kann er als normalen Text lesen.

Vim, Emacs oder IDE (IntelliJ)?

posted on

In welchem Editor kann ich den besten Code schreiben? Vim wie bisher, doch vielleicht besser Emacs oder gar wie meine Kollegen mit einer IDE? Die letzten Wochen habe ich getestet: zwei Wochen nur Emacs und zwei Wochen nur IntelliJ als IDE

Emacs – der andere Texteditor

Mir gefällt, dass er mit Lisp erweitern wird. Ich mag Lisp. Größter Unterschied zu Vim: Keine Unterscheidung zwischen Eingabemodus und Befehlsmodus. Dadurch werden alle Befehle über irgendwelche Tastenkombinationen aufgerufen. Spötter übersetzen Emacs deswegen als Escape-Meta-Alt-Control-Shift. Ja, etwas stört mich das auch, insbesondere wenn ich gerade an einem Mac sitze und viele der Tastenkombinationen erstmal vom Betriebssystem abgefangen werden. Andererseits kenne ich das Problem in VIM, dass ich in den Einfügemodus wechseln woll, obwohl ich schon darin bin. Das führt dann zu so manchem überflüssigen „a“, „i“ oder „A“ im Text.

Beste positive Eigenschaft für mich: ich habe begonnen es zu lieben mit Buffern und Fenstern zu arbeiten. Per Tastenkürzel kann ich in kürzester Zeit die Dateien wechseln, die ich bearbeite und an mehreren Dateien gleichzeitig arbeiten. Bei VIM auch möglich, aber bei Emacs habe ich es wirklich gemacht: der Editor blieb gestartet und wurde nur mit Strg-Z in den Hintergrund gelegt, wenn ich auf der Shell zu tun hatte. Danach „fg“ auf der Shell eingetippt und im Editor war alles wie davor.

Am wenigsten gefiel mir im Vergleich zu Vim hat das Navigieren im Text. Wenn ich per regulärem Ausdruck in VIM etwas suche, so kann ich die Suche jederzeit mit „n“ (vorwärts weitersuchen) oder „N“ (rückwärts weitersuchen) fortsetzen. Das nutze ich beispielsweise gerne, wenn ich Kleinkram ändere. Ich kann nach jeder Änderung mit „n“ zur nächsten Stelle springen. In Emacs dagegen kann ich nur solange weitersuchen wie ich nichts editiere. Danach muss ich erneut die Suche starten.

IDE – IntelliJ

Wie habe ich zu einem Kollegen sagt: es fühlt sich an, wie wenn es nur ein etwas besserer Texteditor ist. – stutze und denke mir: müsste ich das nicht eher von Vim und Emacs behaupten?

Was ich damit meine ist aber: ich habe nicht den Eindruck, dass mein Editor wirklich Struktur im Text erkennt. Ich kann nur Zeichen einfügen und den Cursor bewegen. Alle Funktionen, die verstehen was ein Wort, ein Satz oder ein Absatz in meinem Programm ist wirken nur wie Makros auf höherer Ebene.

Was mich stört: ich habe mich wirklich bemüht alles mit der Tastatur und ohne Maus zu machen, dann der stetige Griff zur Maus nervt mich. Aber es klappt einfach nicht. Zwar scheint es immer auch ein Tastenkürzel zu geben, aber anstatt es zu suchen greift man eben doch zur Maus. Was ich zum Beispiel nicht gefunden habe:

Wenn ich mir meine Kollegen anschaue ist das auch nichts was sich mit der Zeit ändert: ich sehe (und höre im ganzen Büro!) wie oft die Maus im Spiel ist. Meine ideale Entwicklungsumgebung lässt sich gar nicht mit Maus bedienen und zwingt mich zu jedem Tastenkürzel: steile Lernkurve aber danach ein geiles Werkzeug.

Sehe ich einfach nur alles negativ weil es anders als das gewohnte ist? Nein! Es gibt auch Dinge die mir in IntelliJ gefallen haben. Einige Refactorings machen mit IDE mehr Spaß:

Beispielsweise ist es toll einen Codeabschnitt zu markieren und per Tastenkürzel in eine eigene Methode auszulagern. IntelliJ weißt mich auch gleich darauf hin, wenn es ähnliche Codestellen gibt und fragt, ob es diese durch einen Methodenaufruf ersetzen soll. Super! Dennoch lege ich hinterher Hand an und muss die Methode nochmals an die Stelle in der Klasse verschieben wo sie hingehört. IntelliJ fügt sie einfach immer unter der Methode ein von der ich extrahiere.

Prima ist auch, wieviel schneller die Unit-Tests laufen als ein Aufruf von „mvn test“. Das erhöht die Geschwindigkeit eines rot-grün-refactor-Zykluses erheblich.

Das große ABER für mich: schon nach zwei Wochen hatte ich den Eindruck, dass ich schlechteren Code schreibe:

Fazit (für mich)

Code werde ich weiterhin im Texteditor schreiben. Dabei greife ich die letzten Tage mal zu Vim und mal zu Emacs. Ich fühle mich in beiden wohl.

IntelliJ ist nicht schlecht, aber nicht das Werkzeug meiner Wahl zum programmieren. Aber ich kann mir vorstellen, in Zukunft bei größeren Refactorings auf dieses Werkzeug zurückzugreifen.

Mein Weg zur testgetriebenen Entwicklung

posted on

Testgetriebene Entwicklung (TDD) funktioniert – überall. Sie scheitert nicht am Kunden, den nicht Qualität sondern Tempo interessiert. Sie steht nicht im Widerspruch zum jungen Projekt mit wenig Budget, das schnell Kunden gewinnen muss um zu überleben. Sie hindert nicht daran schnell Features umsetzen zu können. Ja, sie macht mir auch nicht (mehr) langsamer.

Es ist keine neun Monate her, dass ich das nicht glauben konnte. Mehrere Anläufe hatte ich unternommen neben Code auch Tests zu schreiben. Länger als zwei Monate ging das nie gut:

Die entscheidenden Hinweise

Test-Driven Development by Example, Kent Beck

Zwei mal klick hat es in meinem Kopf gemacht als ich das Buch „Test Driven Development by Example“ von Kent Beck gelesen habe:

  1. TDD einzuführen ist keine Entscheidung des Kunden, Chefs oder Teams. Das kann jeder für das was er macht selbst tun. Es ist einfach ein Stück persönlicher Programmierstil. Wie ich entscheide, ob ich mir erst auf ein Blatt Papier skizziere was ich programmiere, kann ich auch entscheiden das erst in einem Test zu skizzieren.
  2. Ich hatte davor versucht mit Unit-Tests mehr zu erreichen als ich sollte. Es reicht wenn ich prüfe, dass meine Klasse (Unit) ihre Funktion erbringt und die erwarteten Ergebnisse liefert. Es war falsch zu prüfen, ob mehrere Klassen sich zusammenfügen lassen und gemeinsam richtig arbeiten. Für diese Dinge gibt es Integrations- und Akzeptanztests. Mein Unit-Test stellt nur sicher, dass ich keinen Sonderfall vergesse und sich bei einem Refactoring meiner Klasse (Unit) nichts im Ergebnis ändert.

Mir war klar geworden, dass nicht die Beispiele mit JUnit zu simpel sind, die in fast allen Java-Büchern zu finden sind. Vielmehr war das was ich als Unit betrachtet habe zu komplex. Der Fehler lag nicht in den Beispielen sondern bei mir. Ich hatte meine Probleme nicht so sehr in kleinere Probleme zerlegt, dass sie einfach zu testen sind.

Die ersten sieben Monate

Ein gutes halbes Jahr entwickle ich nur noch testgetrieben. Den Umstieg habe ich geschafft, ich kann mir nicht vorstellen nochmals in die Zeit davor zurückzufallen. Nach einigen Monaten Umstellung habe ich nicht mehr langsamer entwickelt als ohne Tests. Wie bei jeder neuen Technik musste ich am Anfang lernen sie einzusetzen. Das kostet die ersten Wochen und Monate zusätzlich. Dennoch war der Aufand auch damals nicht so hoch wie ich zuvor dachte.

Warum kostet es mich jetzt keine zusätzliche Zeit mehr? Zuerst Tests zu schreiben ist nun eine Struktur in der ich mir Gedanken mache was ich schreiben möchte. Das musste ich auch zuvor tun indem ich Skizzen gemalt, einen Prototypen gebaut oder auch nur Code geschrieben habe, den ich nochmals ändern musste.

Ohne Zusatzaufwand bekomme ich aber die folgenden Dinge frei Haus geliefert:

Was mir sonst noch geholfen hat

Weniger Schlecht Programmieren, Kathrin Passig und Johannes Jander Becoming a Better Programmer, Pete Goodliffe

Zwei Bücher aus den Weihnachtsferien haben meinen Entschluss nur noch mit Tests zu entwickeln gestärkt. In „Weniger schlecht programmieren“ und „Becomming a Better Programmer“ ist mir klar geworden, dass die Professionalität der Entwicklung meine Aufgabe als Entwickler ist. Ich bin der Profi in diesem Bereich und nicht die Geschäftsführung. Diese hat mich dafür angestellt professionell zu arbeiten. Sie verlässt sich darauf, dass ich weiß was notwendig ist und ich dies tue. Wenn ich ihr den Eindruck gebe, es geht auch ohne, wenn es mal sein muss, dann ist klar, dass sie das bevorzugt. Wenn ich der Überzeugung bin, dass es der falsche Weg ist, dann muss ich das vermitteln und darf nicht auf andere schieben, dass es „bei uns“ eben nicht anders geht. Würde ich gegen mein besseres Wissen arbeiten, so hätte zuerst ich versagt und nicht das Management.

Clean Code, Robert C. Martin

Ebenso hat mich der Klassiker „Clean Code“ auf meinem Weg weiter gebracht. Einerseits weil ich durch die Tests erst einiges daraus richtig umsetzen konnte. Vorallem aber weil ich damit gelernt habe auch meine Tests so zu schreiben, dass sie lesbar sind, jederzeit geändert und erweitert werden können.

„ARM Assembly Language - an Introduction“ von J. R. Gibson

posted on

Coverbild ARM Assembly Language von J. R. Gibson Die letzten Tage habe ich das Buch ARM Assembly Language - an Introduction von J. R. Gibson gelesen. Es ist eine Anleitung wie man ARM-Prozessoren in Assembler programmiert. Geschrieben wurde das Buch als Lehrbuch an der Universität Liverpool. Das merkt man, am Ende jeden Kapitels stehen Übungsaufgaben zum Einprägen und Verständnis überprüfen.

Das Buch ist perfekt für Einsteiger in der Assemblerprogrammierung. Der Leser erhält einen ausführlichen Überblick wie er in dieser Sprache programmieren kann. Wird der Einstieg mit einer begleitenden Vorlesung und Übungen unterstützt, so funktioniert das Buch noch besser. Es hilft aber auch, ein paar Grundlagen der Zahldarstellung und der Bit-Manipulation schon zu kennen.

Im Buch wird die ARM-7-Architektur behandelt. Vor allem wird der Prozessor ARM7TDMI betrachtet. Details zu den Prozessoren oder anderer Hardware findet man aber nicht. Dadurch ist das Buch auf für die allgemeine ARM-Programmierung interessant. Wer allerdings die Cortex-M-Prozessoren programmieren möchte, hat mit diesem Buch nicht das richtige. Es behandelt nicht die THUMB-Befehle, die der Cortex-M ausschließlich unterstützt.

Meine Bewertung: 5 von 5 Punkten für den Leser, der Assembler auf einem ARM-Prozessor lernen möchte und motiviert sind auch die Übungsaufgaben zu bearbeiten. Lesen alleine reicht nicht aus.

„C++11“ von Rainer Grimm

posted on

Coverbild C++11 Endlich wissen was in C++11 neu ist, deswegen habe ich „C++11, Der Leitfaden für Programmierer zum neuen Standard“ von Rainer Grimm gelesen. Ein dickes Buch mit 500 Seiten beschreibt was sich in der neuen Version seit 1998 geändert hat oder neu ist. – Und das ist eine Menge.

Immer wieder war ich erstaunt über ungewöhnliche neue Konstrukte und neue Syntax. Solch große Änderungen hatte ich einer reifen Sprache nicht zugetraut. Meine Highlights in C++ sind:

Sehr mutig ist die Spezifikation auch weil sie eine neue Syntax für Funktionen einführt. Bisher definieren wir eine Funktion in der Reihenfolge „Rückgabetyp, Funktionsname und Parameterliste“. In C++ können wir den Rückgabetyp auch hinter die Parameterliste schreiben:

auto fac(int n) -> int {
    return n > 0 ? n * fac(n - 1) : 1;
}

Rainer Grimm geht die Änderungen leicht verständlich an: in drei Durchgängen zeigt er zuerst nur was es neues gibt, im zweiten geht er weiter in die Tiefe der Erweiterungen und im dritten geht er ins Detail. Er Leser kann sich so schnell einen Überblick verschaffen und stolpert in den Details nicht darüber, wenn in Beispielen auch eine andere Neuerung als die gerade erklärte schon benutzt wird. Einziges Manko: im dritten Durchgang bei den Details wurde mir etwas langweilig. Trotzdem ein großartiges Buch dem ich vier von fünf Punkten gebe.

Timing-Fehler auf dem Modbus

posted on

Modbus ist einer Feldbussystem. Eine Steuerung kommuniziert seriell über nur zwei Adern mit mehreren Sensoren und Aktoren. Ich entwickle die RemoteGuard. Diese erfasst Sensordaten so und über andere Schnittstellen und kann dann Aktionen starten oder Daten an unsere M2M-Plattform übertragen.

Für die Entwicklung muss ich oft Sensoren simulieren. Das geht gut und einfach mit einem Arduino. Schnell etwas Hardware zusammengesteckt und Software aufgespielt. Löten meist nicht nötig.

IMG_20131023_134203.jpg Testaufbau von hinten nach vorn: RemoteGuard (groß und blau), Arduino Due mit aufgestecktem RS485-Modul („Shield“) an dem auf der gelben und weißen Ader der MODBUS ankommt, Breadboard um den Arduino mit dem Display zu verschalten, HD44780-Displaymodul, Logikanalysator.

Das Display zeigt Daten der Simulation. Hier habe ich 24 (= 18 hex) Modbus-Nachrichten empfagen. Die letzte Nachricht hatte 3 Byte. Der (fehlerhafte) Inhalt war 11 C1 BC. (Das EF hat keine Bedeutung.)

Das Problem: ich erhalte nicht die erwarteten Nachrichten. Es kommen zwar welche an, das Modul fühlt sich aber nie zuständig. Was ist los? Auf dem Display steht die Nachricht 11 C1 BC. Korrekt wäre aber 01 11 C1 BC. Es fehlt das erste Byte! Die „01“ ist die Modbus-Adresse, „11“ der Funktionscode für „get slave ID“ und zwei Byte Prüfsumme. Auch in allen anderen Nachrichten fehlt das erste Byte, die Prüfsumme ist somit falsch. Klar, solche Nachrichten werden verworfen.

Benutzt habe ich die Bibliothek arduino-modbus-slave. Leider ist darin ein Fehler. Den Beginn einer neuen Nachricht erkennt ein Modbus-Gerät über das Timing auf dem Bus. Vor einer Nachricht wird mindestens 3,5 Zeichen lang nicht gesendet. In der Nachricht dagegen darf keine Übertragungspause gemacht werden. Mein Modbus hat 57000 baud. 3,5 Zeichen (à 11 Bit) sind damit 0,67 ms lang. Arduino-modbus-slave berechnet dies ohne Nachkomma. Alles hinter dem Komma wird abgeschnitten. Jede Pause ab 0 ms Länge wird als Beginn einer neuen Nachricht betrachtet … Freundlich gesagt: das ist nicht gaaanz richtig. Eine Pause von 0 ms Länge, die gab es natürlich überall.

Problem erkannt, Problem gebannt: ein kleiner Patch und die Bibliothek rundet dies auf 1 ms auf. (Den Bug habe ich in den Issue-Tracker von arduino-modbus-slave eingetragen. Mal schauen, ob sich jemand darum kümmert.)

Wie signalisiert MODBUS die Grenzen zwischen Nachrichten?

Wenn man sich das MODBUS-Protokoll anschaut, dann sieht man, dass einzelne Nachrichten (nur) durch eine Pause von der Dauer der Länge, die 3,5 Zeichen zur Übertragung bräuchten signalisiert wird. Es gab' also zwei Möglichkeiten: meine RemoteGuard hat schickt Nachrichten nicht am Stück raus und macht eine zu lange Pause innerhalb der Nachricht oder mein gebautes Sensormodul erkennt eine Pause wo keine Pause ist. Ein typisches Timing-Problem also.

Einen solchen Fehler durch Programmcode-Analyse zu finden ist ziemlich aufwändig. Man müsste zu mehreren Zeitpunkten einen Timer auslesen und dann schauen zu welchen Zeiten was passiert ist. Eine Nerven raubende Angelegenheit … Viel angenehmer geht es, wenn man einen Logik-Analysator zur Hand hat.

Ein Logik-Analysator ist so etwas wie ein Oszilloskop jedoch nicht für analoge Signale sondern für Digitalsignale.

Saleae_Logic_MODBUS.png Screenshot vom Logik-Analsator. Entsprechend konfiguriert dekodiert er automatisch das serielle Signal. Man sieht es kommen die Bytes 00 11 C1 BC an. (Im Gegensatz zur Displayanzeige im Foto oben hatte ich den die MODBUS-Adresse von 1 auf 0 geändert.) Die Anzeige der Bytes im Screenshot ist dezimal.

Die Punkte im Bild sind die einzelnen Bits auf der seriellen Leitung. Das erste Byte beginnt mit einem Startbit (LOW-Pegel), hat 8 Datenbits (alle LOW-Pegel), ein Parity-Bit (ebenso LOW) und ein Stopp-Bit (HIGH). Dann kommt das Startbit des zweiten Byte, gefollgt von 8 Datenbits, einem Parity und dem Stoppbit. Man sieht auch schön wie auf der seriellen Leitung immer zuerst das niederwertigste Bit übertragen wird.

Über die Anzeige im Logik-Analysator war schnell klar: die RemoteGuard sendet die MODBUS-Nachricht korrekt. Alle Bytes der Nachricht werden in einem Weg übertragen. Es gibt keine Pause von 3,5 oder mehr Zeichen in der Übertragung. Der Fehler musste also in meinem Modul-Testaufbau bzw. in der hierfür verwendeten Bibliothek liegen.

Die verwendete Bibliothek ist arduino-modbus-slave. Und in ihr war der Fehler auch schnell gefunden. Sie berechnet das was als notwendige Länge zwischen zwei Nachrichten angesehen wird als Ganzzahl in Millisekunden. Mein bus läuft mit 57600 baud. Bei einer Zeichenlänge von 11 Bit (Startbit, 8 Datenbit, Parity und Stoppbit) sind 3,5 Zeichen nur etwa 0,67 ms lang. Als Ganzzahl ergibt dies eine Länge von 0 ms. So viel „Pause“ ist eben immer und zwischen allen Bytes, die übertragen werden. Indem ich die Pausenlänge statt abzurunden nun aufrunde erhalte ich 1 ms und alles funktioniert.

Den entsprechenden Bug habe ich auch im Bugtracker des Projektes gemeldet. Mal schauen, ob sich ihm jemand annimmt.

DNSsec-Signaturen überprüfen mit Bind

posted on

Wer einen authoritativen Nameserver betreibt sollte die eigenen Zonen mit DNSsec sichern. Hier zeige ich euch, wie ihr einen rekursiven Nameserver so einrichtet, dass der DNSsec-Signaturen prüft. Was ist der Unterschied? Authoritative Nameserver sorgen beim Besitzer einer Domain, dass diese gefunden werden kann. Rekursive Nameserver suchen für einen Internetanschluss die richtige Verbindung zu fremden Domains.

Warum soll ich DNSsec aktivieren?

Klar gibt es auch immer ein paar Nachteile:

Manche meinen ein weiterer Nachteil sei, dass die Signaturen bei DNSsec nicht im Client sondern im Nameserver des Zugangsproviders geprüft werden. Die Verbindung zwischen Provider-Nameserver und Client sei so nicht geschützt. Dieses Problem lässt sich jedoch leicht dadurch lösen, dass der Client selbst Signaturprüfungen vornimmt. Wenn er das nicht tut, kann man dies nicht dem Protokoll anlasten.

Meiner Ansicht nach überwiegen die Vorteile bei weitem.

Umkonfiguration von Bind

Wir können DNSsec bei der Namensauflösung in bind sehr einfach aktivieren. Im options-Bereich der Konfigurationsdatei müssen nur zwei Zeilen eingetragen werden:

options {
        directory "/var/cache/bind";
        
        auth-nxdomain no;    # conform to RFC1035
        listen-on-v6 { any; };

        allow-recursion { 127.0.0.1; ::1; };

        dnssec-enable yes;
        dnssec-validation yes;
};

Die Einstellung „dnssec-enable“ aktiviert den grundlegenden Support für DNSsec in Bind. Die Einstellung „dnssec-validation“ aktivert, dass beim Auflösen von Domains die DNSsec-Signaturen mit angefordert und überprüft werden.

Überprüfen, ob eine Domain DNSsec unterstützt

Mit der neuen Konfiguration gehört jede Namensauflösung in eine von zwei Kategorien:

  1. Die aufgelöste Domain ist nicht mit DNSsec geschützt. Das Ergebnis ist nicht sicherer als bisher.
  2. Die aufgelöste Domain ist durch DNSsec geschützt. Das Ergebnis, das wir bekommen, wurde von Bind überprüft. Wenn die Überprüfung fehlschlägt bekommen wir das Ergebnis gar nicht mehr.

Wie können wir feststellen in welchen dieser beiden Fälle eine Namensauflösung gehört? Entweder wir installieren uns ein Plugin in den Webbrowser. Der DNSsec-Status wird dann in der Adressleiste angezeigt. (z.B. hier für Firefox, hier für Chrome und hier für den Internet Explorer).

Auch auf der Kommandozeile können wir eine Domain überprüfen. Wie für alles hat der Befehl dig auch hierfür die passende Option: +dnssec. Der Parameter lässt dig den DNSsec-Status vom Resolver anfordern. Dieser wird dann von dig mit ausgegeben. Im Header wird hierzu das Flag „ad“ angezeigt, wenn die DNSsec-Prüfung erfolgreich war:

# dig switch.ch +dnssec

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> switch.ch +dnssec
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 36976
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 3, ADDITIONAL: 10

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;switch.ch. IN A

;; ANSWER SECTION:
switch.ch. 60 IN A 130.59.108.97
[...]
;; Query time: 330 msec
;; SERVER: ::1#53(::1)
;; WHEN: Mon May  6 21:33:12 2013
;; MSG SIZE  rcvd: 1211

Achtung Falle: Wer so testen will, ob die eigene Zone korrekt mit DNSsec gesichert ist, kann falsche Ergebnisse bekommen. Wenn ein Nameserver eine Anfrage zu einer selbst gehosteten Domain beantwortet ist das ad-Flag nie gesetzt. Das liegt daran, dass er in diesem Fall keine Überprüfung der Signaturen durchgeführt hat. Das muss er auch nicht, da er bereits weiß, dass die Daten korrekt sind.

Wollt ihr eure eigene Zone überprüfen? Der öffentliche Nameserver von Google macht das für euch: dig example.com +dnssec @8.8.8.8 (8.8.8.8 ist eine der IP-Adressen unter denen Google öffentliche Nameserver betreibt.)

Eingesperrt von Google

posted on

Seit einigen Jahre macht sich WhatsApp auf den Smartphones meiner Kontakte breit. Natürlich werde ich von meinen Bekannten auch immer wieder aufgefordert das Programm doch zu installieren. Ich wollte das nie. Mir war es zuwider mich auf einen proprietären Dienst einzulassen wenn es offene Alternativen gibt. Diese offene und Anbieter übergreifende Alternative war und ist Jabber bzw. XMPP (zwei Namen für das gleiche).

Nun ist dies erst einmal aber nur ein Protokoll und damit nichts was man nutzen könnte. Was ein Jabber-Nutzer braucht ist ein Programm und Diensteanbieter. Hierfür war meine Empfehlung bisher Google Talk. Als Programm super integriert und vorinstalliert auf jedem Android-Telefon. Eine einfach zu bedienende Oberfläche, die auch für einen „Normalmenschen“ verständlich ist. Nichts was von Freaks für Freaks gemacht ist. Als Anbieter stand Google mit einem super stabilen Dienst dahinter.

Bisher eine tolle Sache: einerseits konnte man komplett abgestimmt alles aus einer Hand bekommen, andererseits konnte man mit Nutzern bei anderen Anbietern chatten und wenn man wollte sogar einen eigenen Server installieren. Echt klasse!

Mit meiner Weigerung ein geschlossenes Messaging zu nutzen und meinem andauernden Hinweis auf die freie Alternative habe ich auch einige Freunde und Bekannte zu Google Talk gebraucht.

Aus Google Talk wird Hangouts

Zur diesjährigen Konferenz Google I/O wurde „Talk“ nun zu „Hangouts“. Ein soweit vernünftiger Schritt. Google hat in den letzten Jahre mehrere miteinander nicht wirklich sinnvoll verzahnte Kommunikationsdienste gestartet. Neben „Google Talk“ gab es „Google Voice“, „Google+ Messenger“ die bisherigen „Hangouts“ und eine Zeit lang sogar „Google Wave“. Für einen Nutzer hat es keinen Sinn gemacht das gleiche über verschiedene Produkte machen zu können. Auch für mich war es verwirrend einen Kontakt mehrfach online zu sehen: mal als Talk-Kontakt, dann als Google+-Kontakt und als was weiß ich noch. Wieso sollte ich bevor ich mit jemandem chatten oder (video)telefonieren wollte erst überlegen in welchem Programm ich das mache? Ich habe also überhaupt nichts dagegen einzuwenden, dass hier aufgeräumt wurde und die verschiedenen Kommunikationswege unter eine Haube mit dem Namen „Google Hangouts“ gebracht werden. – Im Gegenteil: das ist eine prima Sache. Die Nutzung eines Kommunikationsdienstes muss einfach und übersichtlich sein.

Tatsächlich passiert ist aber gleichzeitig noch etwas viel weitreichenderes: Google hat beschlossen die eigenen Nutzer ihrer Plattform nicht mehr mit Nutzern anderer Anbieter kommunizieren zu lassen. Nikhyl Singhal, Direktor Produktmanagement für Echtzeitkommunikation bei Google drückt das (ab 5:07 in unten stehendem Video) so aus: „Hangouts is not based on top of the XMPP standard. […] We have essentially made a hard decision to focus less on the XMPP standard and more on what are users looking for.“ (Hangouts baut nicht auf den XMPP-Standard auf. Wir haben im Wesentlichen die schwere Entscheidung getroffen uns weniger nach dem XMPP-Standard zu richten und mehr danach was Nutzer suchen.“) Nun das klingt vielleicht gut, ist inhaltlich aber Mist.

Wie oben schon erwähnt ist XMPP ein Protokoll und nichts was Nutzer direkt nutzen. Nach was die Nutzer schauen ist das Nutzungserlebnis, die Oberfläche und der Funfaktor eines Dienstes. Wo liegt da der Widerspruch? Wieso sollte man wenn man sich hierauf konzentriert darunter nicht XMPP benutzen? XMPP ist das „eXtensible Messaging and Presence Protocol“ (erweiterbares Protokoll für Nachrichtenvermittlung und Präsenz). Das Schlüsselwort hierbei ist extensible bzw. erweiterbar. Es ist gar kein Problem in XMPP all die schönen Dinge zu tun, die Google mit Hangouts machen möchte.

Ich denke, der Grund wieso Google die eigene Plattform gegen außen abschottet ist auch ein ganz anderer: der Nutzer soll an Google gebunden werden. Man möchte es einfach nicht mehr, dass auch mit Kontakten bei anderen Anbietern die Kommunikation möglich ist. Man möchte, dass diese Kontakte auch zu Google kommen müssen.

Das ganze ist ähnlich wie die Einstellung von Google Reader nächsten Monat. Auch dies war ein offener Standard über den ein Google-Nutzer Nachrichtenfeeds von anderen Anbietern abonnieren und lesen konnte. Auch dieser Dienst wird eingestellt, da man es lieber sieht, dass der Nutzer sich seine Nachrichtenfeeds über die geschlossene Platform „Google+“ bezieht.

Was nun?

Für mich ist der Grund wieso ich Talk anstatt anderer Messenger benutzt habe weggefallen. Ich will nicht in den Dienst eines Providers eingesperrt sein. Meine bisher bei Google gehostete Jabber-Adresse m@tthias.eu läuft seit gestern wieder auf einem freien Server. Noch bin ich unter der gleichen Adresse auch bei Google Talk/Hangouts erreichbar. Aber vermutlich wird dies über kurz oder lang ein Ende haben. Bis dahin bin ich noch auf der Suche nach einem benutzerfreundlichen und gut mit Mobilfunkverbindungen klarkommenden Jabber-Programm für Android. Wer weiß, vielleicht gibt es das ja schon und ich kenne es nur noch nicht. Nach der Ankündigung, dass Google Reader eingestellt wurde, war ich auch überrascht welche tolle Alternative ich in Feedly finden konnte. Empfehlungen nehme ich gerne entgegen.

Und WhatsApp? Wenn Google nicht mehr besser ist, werde ich nun auch das unterstützen „was alle eh schon haben“? Nein, ich denke nicht.

Weitere Infos in folgenden Artkeln:

DHL: Erfolgloser Zustellversuch, Empfänger nicht zu Hause

posted on

Ich kann mal wieder von DHL berichten: ich habe dringend ein Buch benötigt und Amazon konnte dies nur noch mit der Lieferoption „Morning Express“ am nächsten Tag liefern. Nicht schlecht, dachte ich: da die Lieferung an einem Freitag und ins Büro erfolgt, ist es super die Sendung „garantiert“ vor zwölf Uhr zu erhalten.

Am Tag der Zustellung schaue ich also immer mal wieder aus dem Fenster des Büros, wenn ein Paketdienst vorbeifährt. Mittag kommt immer näher und ich wundere mich, dass die Sendung noch nicht angekommen ist. Es wird doch hoffentlich alles klappen? Ich brauche das Buch dringend um mich auf einen Kundentermin vorzubereiten.

Punkt zwölf Uhr kommt der Paketboote – fast ein wenig außer Atem – durch die Türe und hat mein Paket in der Hand. „Das hat ja gerade noch geklappt,“ denke ich schmunzelnd und nehme das Paket entgegen.

Wirklich verärgert hat es mich nun aber, als ich am Wochenende ins Tracking von DHL geschaut habe. Ich wollte wissen, welche Uhrzeit DHL als Zustellzeitpunkt erfasst hat. Dabei stelle ich fest, dass angeblich schon eine halbe Stunde zuvor ein Zustellversuch stattgefunden habe, jedoch der Empfänger nicht anzutreffen war. („Erfolgloser Zustellversuch. Empfänger nicht zu Hause.“)

Was ist denn das für ein Unsinn? Die Lieferung ging an eine Firmenadresse. Einerseits saß ich im Büro und habe auf die Lieferung gewartet und andererseits waren zusätzlich auch noch Kollegen im Büro, die die Sendung genauso hätten annehmen können – wenn denn jemand da gewesen wäre, der einen Zustellversuch unternommen hätte.

Es scheint mir doch sehr, als habe der Kurier hier einfach schon einmal einen Zustellversuch in seinem Gerät vermerkt, ohne dass er vor Ort gewesen wäre. Vermutlich war im klar, dass es knapp wird mit der rechtzeitigen Zustellung. Die Liefergarantie gilt nämlich nur für den ersten Zustellversuch.

Mein DNSsec-Setup

posted on

Vor ein paar Tagen habe ich bereits über einen Teil meines Nameserver-Setups mit Bind geschrieben. Ich habe erklärt, wie DDNS mit bind verwendet werden kann um beispielsweise Kunden die Möglichkeit zu geben Änderungen an Ihren Zonen über ein standardisiertes Protokoll durchzuführen oder die sich häufiger ändernde IP des Internetanschlusses zuhause immer aktuell im DNS zu hinterlegen. Dabei habe ich erwähnt, dass ein interessantes Argument für den Einsatz von DDNS zum Updaten von Zonen auch ist, dass bind in diesem Fall sich automatisch darum kümmert diese erneut zu signieren. Wie dieses Setup funktioniert möchte ich in diesem Artikel beschreiben.

Ziele meines Setups

Wenn man versucht etwas kryptografisch abzusichern, dann sollte der erste Schritt immer der gleiche sein. Es ist zu bestimmen, gegen welche Arten von „Angriffen“ man sich schützen möchte. Je nachdem was man sich hier für Vorgaben macht kommt man zu teilweise komplett verschiedenen „optimalen Lösungen“.

In meinem Setup kommt es mir nicht darauf an die höchstmögliche Sicherheit herzustellen. Vielmehr ist das Ziel meines DNSsec-Einsatzes die Grundsicherheit zu erhöhen. Einfache Angriffe mit dem Ziel DNS-Einträge im Cache von DNS-Resolvern zu verfälschen sollen verhindert werden. DNSsec soll bei mir deswegen möglichst breit und damit für alle Zonen verwendet werden. Es ist deshalb wichtig, dass möglichst kein zusätzlicher Aufwand in der Verwaltung der Zonen entsteht oder dieser nur minimal ist.

Indem ich bei meinem Setup die zur Signatur der Zonen genutzten Private-Keys auf meinem Server ablege(n muss), habe ich an einem anderen Punkt jedoch keinen erhöhten Schutz meiner Zonen: wenn es einem Angreifer gelingt durch irgendeine Lücke in meinen DNS-(Master-)Server einzudringen, so kann er Modifikationen an meiner Zone vornehmen und für diese trotzdem eine gültige Signatur erzeugen.

Ein weiterer Punkt bei dem mein Setup keine Verbesserung der Sicherheit bringt ist der Schutz gegen Angriffe, die meine Zonen unerreichbar machen. Es gibt sogar Überlegungen, dass der Einsatz von DNSsec prinzipiell die Sicherheit im Internet gegen DOS-Angriffe vermindert. Bei der DNS Amplification Attack werden DNS-Server genutzt um andere Server mit einem DOS-Angriff zu überziehen. Die Aktivierung von DNSsec vergrößert dabei die Gefahr, dass der eigene DNS-Server hierfür missbraucht wird.

Konfiguration von bind

In diesem Abschnitt erkläre ich welche Änderungen an den Konfigurationsdateien von bind vorgenommen werden müssen, damit die eigenen Zonen signiert ausgeliefert werden. Wie sich zeigen wird ist dies gar nicht viel. Es reichen zwei kleine Änderungen.

Grundsätzliches aktivieren von DNSsec

Damit bind grundsätzlich den Umgang mit DNSsec aktiviert, muss dies in der Konfiguration im options-Abschnitt angegeben werden:

options {
    directory "/var/cache/bind";

    auth-nxdomain no;    # conform to RFC1035
    listen-on-v6 { any; };

    allow-recursion { 127.0.0.1; ::1; };

    dnssec-enable yes;
    dnssec-validation yes;

    allow-transfer {
        key doux.amessage.eu.;
        key eder.amessage.eu.;
    };
};

Zur Aktivierung muss hier einfach der Eintrag „dnssec-enable yes;“ angegeben werden. (Der Eintrag „dnssec-validation yes;“ ist nicht notwendig und auf einem reinen autoritativen Nameserver auch nicht sinnvoll. Der Eintrag ist bei mir nur vorhanden, da ich meinen bind für localhost als recursive DNS-Server nutze.)

Diese Konfigurationsänderung muss sowohl auf dem Master-Nameserver wie auch auf allen Slave-Nameservern erfolgen.

Den einzelnen Zonen mitteilen wo sich die zugehörigen Keys befinden

Die zweite notwendige Änderung ist es, dass die Definition der Zone noch um zwei Zeilen erweitert wird:

zone "mwimmer.com" in {
    auto-dnssec maintain;
    type master;
    notify yes;
    file "/etc/bind/zones/mwimmer.com.zone";
    update-policy {
        grant root.user.invalid.     subdomain mwimmer.com. ANY;
        grant matthias.user.invalid. subdomain mwimmer.com. ANY;
    };
    allow-transfer {
	key root.user.invalid.;
	key doux.amessage.eu.;
        key matthias.user.invalid.;
    };
    key-directory "/etc/bind/keys";
};

Hier habe ich über „auto-dnssec maintain;“ bind mitgeteilt, dass er bei Updates der Zone diese automatisch neu signiert. Außerdem habe ich mit „key-directory "/etc/bind/keys";“ angegeben wo bind nach den notwendigen Private-Keys zur Signatur der Zone sucht. Ohne letzteren Eintrag würde bind in seinem working Directory suchen. Dieses ist auf einem Debian-System (wie man auch im vorherigen Config-Ausschnitt sieht) /var/cache/bind, was für eine Ablage der DNSsec-Keys nicht geeignet ist, da dieses Verzeichnis normalerweise nicht mit gebackupt wird.

Diese Änderung ist nur auf dem Master-Nameserver notwendig.

Einrichten einer Zone

Zum Einrichten einer neuen Zone auf meinem Nameserver erstelle ich hierfür zuerst eine normale, nicht signierte Zonendatei. Außer den Einträgen auto-dnssec und key-directory in der Bind-Konfiguration, die ich sofort mit eintrage, wird die Zone also zuerst vollkommen normal und ohne Signaturen angelegt und mit einem Aufruf von rndc reconfig auch aktiviert. (Wurde die Konfiguration einer bestehenden Zone geändert um beispielsweise bei einer bereits vorhandenen Zone DNSsec nachzurüsten, so muss stattdessen rndc reload benutzt werden.)

Die Zone wird ab diesem moment von bind ausgeliefert, ist aber noch unsigniert. Im nächsten Schritt geht es jetzt also darum die notwendigen DNSsec-Schlüssel zu erzeugen. Es werden hierzu zwei Schlüsselpaare erzeugt. Das eine paar ist der Key-Signing-Key (KSK). Ein Fingerabdruck hiervon sollte soweit möglich später in die übergeordnete Zone hinterlegt werden. Mit diesem Key-Signing-Key wird später von bind das zweite Schlüsselpaar, der sogenannte Zone-Signing-Key (ZSK), unterschrieben. Erst mit dem Zone-Signing-Key werden dann tatsächlich die eigenen Records in der Zone unterschrieben.

Die Erstellung der beiden Schlüsselpaare erfolgt mit dem Tool dnssec-keygen, das Teil der bind-Distribution ist (Debian-Paket: bind9utils):

dnssec-keygen -K /etc/bind/keys -a RSASHA512 -b 2048 -f KSK mwimmer.com
dnssec-keygen -K /etc/bind/keys -a RSASHA512 -b 1024 mwimmer.com

Je nachdem wie viel Entropie auf eurem System vorhanden ist, kann die Erzeugung dieser zwei Schlüsselpaare durchaus mehrere Stunden beanspruchen. Also nicht verzweifeln, wenn lange Zeit nichts vorwärts geht. Am besten startet ihr die Schlüsselerzeugung also in einem screen.

Nach der Erstellung der Schlüsselpaare muss noch sichergestellt werden, dass die Schlüssel von bind gelesen werden können. Da dnssec-keygen den Private-Key nur für den Datei-Owner lesbar macht (Zugriffsrechte „rw-------“) müssen wir auf einem Debian-System die erzeugten Dateien beispielsweise dem User „bind“ zuweisen.

Wenn nun beide Schlüsselpaare erzeugt und für bind lesbar sind, müssen wir bind noch mitteilen, dass er diese Keys ab sofort zur Signatur der Zone verwenden soll: rndc sign mwimmer.com

Voilà: bind liefert ab diesem Moment eine signierte Zone aus und kümmert sich auch darum, wann die Zone neu signiert werden muss.

Signaturen der Zone in der übergeordneten Zone eintragen (lassen)

Damit fremde Nameserver die Signaturen in der Zone prüfen können, müssen diese wissen welche Keys überhaupt berechtigt sind die Zone zu signieren. Bei DNSsec geschieht dies, indem die Signatur(en) des/der berechtigten Keys in die übergeordnete Zone eingetragen werden. Die Keys mit denen ich die Zone „mwimmer.com“ signiere sind entsprechend also in der Zone „com“ eingetragen. Indem die Zone „com“ wiederum selbst signiert ist und deren Schlüssel in der DNS-Root-Zone eingetragen ist usw. reicht es auf anderen Nameservern aus, dass dort nur die gültigen Keys für die Root-Zone eingetragen werden müssen. Die Funktionsweise ist also sehr ähnlich zu der von X.509-Zertifikaten. Auch bei diesen müssen einem Browser nur die Stammzertifikate der Zertifizierungsstellen bekannt.

Wie konkret in die übergeordnete Zone eingetragen wird was die gültigen Key-Signing-Keys sind ist sehr unterschiedlich. Was man allgemein nur sagen kann ist, dass dieser Eintrag über den Registrar erfolgt bei dem man die Domains registriert hat. Ob dieser DNSsec überhaupt unterstützt und wenn ja wie man ihm die Keys bekannt macht, ist von Registrar zu Registrar verschieden.

Ich persönlich habe mir für InterNetX entschieden und bin wegen DNSsec extra zu diesem Provider gewechselt, da meine vorherigen Provider leider alle nicht in der Lage waren DNSsec-Signaturen anzunehmen.

Außerdem ist es auch so, dass noch nicht bei allen Top-Level-Domains überhaupt eine Delegation mit DNSsec möglich ist. Bei den meisten größeren TLDs (z.B. .DE, .com, .net, .org, .eu) ist dies allerdings kein Problem mehr.

Ich möchte euch noch kurz zeigen, wie die Konfiguration der DNSsec-Delegation vom Falle von InterNetX geschieht.

DNSsec bei InterNetX (AutoDNS 3.0)

Hinweis vorweg: DNSsec unterstützt das Eintragen der Fingerprints von DNSsec-Schlüsseln in die übergeordneten Zonen. Wenn man DNSsec benutzen möchte, so muss man die Nameserver jedoch (mit den oben beschriebenen Einstellungen) selbst betreiben. Die Nameserver, die man über den AutoDNS verwalten kann, sind selbst nicht für DNSsec aktiviert.

Damit InterNetX die Signatur des Schlüssels mit dem wir unsere Zonen signieren an die übergeordnete Registry weiter gibt, müssen wir unseren öffentlichen Teil des Key-Signing-Keys bei der jeweiligen Zone hinterlegen. Damit der entsprechende Reiter bei der Zone im AutoDNS erscheint, müssen wir „DNSSEC aktivieren“ in den Einstellungen der Benutzeroberfläche aktivieren.


Grundsätzliches aktivieren von DNSsec in der Oberfläche des AutoDNS 3.0

Nachdem diese Einstellung aktiviert ist, erhalten wir in der Domainverwaltung wenn wir eine Domain bearbeiten einen zusätzlichen Reiter „DNSSEC“:


Reiter „DNSSEC“ in der Oberfläche des AutoDNS 3.0

In diesem Reiter müssen wir den verwendeten Algorithmus unseres Key-Signing-Keys eintragen (in obigem Beispiel haben wir einen RSASHA512-Schlüssel erzeugt, wir wählen also „10 (RSA/SHA-512)“. Außerdem tragen wir den BASE64-enkodierten öffentlichen Schlüssel (public Key) in das darunter stehende Eingabefeld ein. Zu diesem öffentlichen Schlüssel kommen wir am einfachsten, wenn wir unseren Nameserver fragen:

dig mwimmer.com DNSKEY | grep 257

Hinweis: Ich habe die Erfahrung gemacht, dass es mit AutoDNS 3.0 bei DE-Domains nicht funktioniert, wenn ich den DNSsec-Schlüssel bereits bei der Registrierung mit angebe. Die Domain wird dann zwar registriert, aber der Fingerprint des DNSsec-Keys nicht mit eingetragen. Ich habe mir deswegen auch bei der Registrierung angewöhnt diese zuerst ohne DNSsec durchzuführen und wenn sie fertig ist, bearbeite ich die Zone nochmals und trage die DNSsec-Einstellungen im AutoDNS 3.0 nach.

DDNS mit Bind einrichten

posted on

Der Nameserver Bind bringt von Hause aus die Möglichkeit mit, dass Änderungen in Zonen dynamisch durchgeführt werden können. Dies kann zum Beispiel genutzt werden um selbst etwas wie DynDNS zu realisieren. In der Tat nennt sich das was Bind da implementiert auch DDNS. Spezifiziert ist das Protokoll in RFC 2136: Dynamic Updates in the Domain Name System (DNS UPDATE).

Da ich heute eh den größten Teil dieses Textes als Mini-HOWTO für einen Kollegen geschrieben habe, möchte ich ihn auch hier auf meinem Weblog für andere zur Verfügung stellen. Alle hier verwendeten Befehle sind Befehle von Bind. Unter Debian sind diese Utility-Befehle im Paket dnsutils verpackt. Aktuell benutze ich die Version 9.8.4 von Bind.

Ich zeige in diesem Artikel:

  1. wie man einen kryptografischen Schlüssel zur Sicherung des Zugriffs erstellt,
  2. wie die Konfiguration von Bind angepasst wird,
  3. wie dynamische Updates an Bind geschickt werden und
  4. was zu beachten ist, wenn weiterhin auch klassische Updates an der Zone durchgeführt werden sollen.

Bei max.example.com handelt es sich im folgenden um den Namen des erzeugten Keys. Dieser hat die Form einer Domain, muss aber nicht zwangsläufig einer existierenden Domain entsprechen. Ich empfehle die E-Mail-Adresse des Schlüsselinhabers in dem das @-Zeichen durch einen Punkt ersetzt ist zu verwenden (im Beispiel wäre als die E-Mail-Adresse des Inhabers max@example.com). Bei example.net um die Zone, die für DDNS konfiguriert werden soll. Ein Key kann dabei für mehrere Zonen gemeinsam genutzt werden. Genauso ist es möglich mehreren Keys die Änderung einer Zone zu erlauben.

Key erzeugen

# dnssec-keygen -a HMAC-SHA512 -b 512 -n USER max.example.com

Das kann einen Moment dauern. Es entstehen zwei Dateien mit den Namen Kmax.example.com.*.key und Kmax.example.com.*.private. Beide Dateien enthalten den gleichen Key in unterschiedlichen Formaten, da wir für DDNS einen symmetrischen Key benutzen (d.h. kein Public-Key-Verfahren). Entsprechend muss der Inhalt beider Dateien geheim gehalten werden.

Konfigurieren von Bind

Zuerst muss der erzeugte Schlüssel in die Konfiguration von bind eingefügt werden:

key max.example.com. {
    algorithm hmac-sha512;
    secret "nc/Q3sL8LDpBE6XpPFdXji2VlhRirN3zxIErqA8xmS8JSMbqQ1PGZrAEdTHl0ekduiQGwDt9zicKtJCSBvaLJw==";
};

Der Inhalt von „secret“ ist dabei aus der Datei Kmax.example.com.*.key übernommen.

Außerdem wird die Konfiguration der Zone angepasst indem eingetragen wird mit welchem Key welche Änderungen gemacht werden dürfen:

zone "example.net" in {
    type master;
    notify yes;
    file "/etc/bind/zones/example.net.zone";
    update-policy {
        grant max.example.com.         subdomain example.net. ANY;
    };
};

Neu eingefügt ist hier der „update-policy“-Abschnitt. (Es gibt auch das Keyword allow-update, da kann man allerdings nicht konfigurieren was (nicht) geändert werden darf mit einem Key.)

Bind muss damit alles funktioniert Schreibzugriff auf die Zonenfiles und das Verzeichnis in dem diese liegen haben.

Editieren der Zone mit DDNS-Befehlen

# nsupdate -k Kmax.example.com.*.private
update delete example.net A
update add example.net 500 A 192.0.2.128
send
quit

Manuelles Editieren des Zonefiles

Wenn für eine Zone DDNS aktiv ist, dann darf nicht mehr einfach das Zonenfile geändert werden. Grund hierzu ist, dass Bind nicht für jede Änderung eine neue Version des Zonenfiles erzeugt sondern ein Journal anlegt. (Datei wie die Zonendatei plus Endung *.jnl.) Um die Zonendatei zu editieren muss bind gesagt werden, dass er keine weiteren Updates für die Zone annimmt und alle vorhandenen Updates in die Zonendatei schreibt. Das geht mit:

# rndc freeze example.net

Jetzt kann die Zonendatei editiert werden.

# rndc thaw example.net

Mit dem "thaw"-Kommando von rndc wurde die Annahme von Updates wieder aktiviert und gleichzeitig Bind instruiert die Zonendatei neu einzulesen, also gemachte Updates zu übernehmen.

Ich habe inzwischen aber komplett aufgehört Zonendateien auf diesem Weg zu editieren. Ich mache alles über nsupdate. Das hat den großen Vorteil, dass nichts schiefgehen kann. nsupdate übernimmt einerseits nur korrekte Änderungen und kümmert sich andererseits auch automatisch darum, dass der Serial im SOA-Record inkrementiert wird. Wenn DNSsec auf dem Nameserver aktiviert ist, so sorgt sich nsupdate sogar darum, dass die Zone automatisch neu signiert wird.

Probleme beim Zugriff auf das S-Trust Zertifikatsverwaltungssystem

posted on

Fehler bei der Initialisierung der ZKA-SIG-API-Umgebung
Notwendige Komponenten zum Betrieb der ZKA-SIG-API konnten nicht gefunden werden. Eventuell liegt eine unvollständige bzw. fehlerhafte Installation vor.
Zur Lösung des Problems suchen Sie bitte die folgende Seite auf: https://www.s-trust.de/service_support/chipkartenleser/kartenlesersupport/

Diese Meldung habe ich heute bekommen als ich auf das S-Trust Zertifikatsverwaltungssystem zugreifen wollte. Grund war, dass ich meine CSA-PIN entsperren musste.


S-Trust Signaturkarte

Als erstes habe ich die auf der Website von S-Trust gegebenen Ratschläge ausgeführt:

  • Das Tool "ZKA Komponenten aktualisieren" des Herstellers meines Chipkartenlesegerätes ausgeführt.
  • Eine spezielle Version des Treibers meines Chipkartenherstellers installiert (was unständlich war, da schon ein neuerer Treiber auf meinem System installiert war und zuvor der alte Treiber deinstalliert werden musste).
  • Außerdem habe ich die installierten Module in meinem Chipkartenleser geprüft und ebenso überprüft ob ein Firmwareupdate für meinen Leser verfügbar ist.

Trotz diversem hin und her und einigen Reboots hat es einfach nicht funktioniert. Immer wieder kam die obige Fehlermeldung.

Ich musste also in den sauren Apfel beißen und die Hotline von S-Trust anrufen. Das ist ärgerlich, da sie nur über eine 0900-Rufnummer erreichbar ist und solche Anrufe ich nicht vom Festnetz tätigen kann. Mein Festnetzanbieter vermittelt nicht zu 0900. Wohl oder übel musste ich also vom Handy aus anrufen. Mein Mobilfunkanbieter verlangt hierfür stolze 1,79 € pro Minute.

Am Telefon hatte ich ohne große Wartezeit einen sehr freundlichen und kompetenten Mitarbeiter. Sehr schnell hatte er das Problem erfasst:

Reiner SCT, der Hersteller meines Chipkartenlesegerätes installiert die Datei zkasigapi.dll in den Ordner $JAVA_HOME/lib/ext/x86. Das Java-Applet von S-Trust sucht diese DLL dagegen im Ordner $JAVA_HOME/bin. Nachdem ich die DLL-Datei vom ersten Ordner in den zweiten Ordner kopiert hatte funktionierte alles einwandrei.

Wer hier für den Fehler verantwortlich ist (Reiner SCT oder S-Trust) kann ich nicht beurteilen. Auf jeden Fall wäre es aber schön gewesen die Lösung für das Problem auch auf der Support-Seite von S-Trust zu finden. Ich hatte nach der Fehlermeldung gegooglet und nichts gefunden. – Mit meinem Blogpost hier hoffe ich zumindest letzteres Problem für alle anderen denen es wie mir geht zu lösen.

Die Cloud und ich … was das Aus von Google Reader für mich bedeutet.

posted on

Schon länger habe ich eine zwiespältige Einstellung gegenüber „der Cloud“. Manche würden wohl sogar sagen, das hätte ich schon immer gehabt. Allerdings meine ich, dass ich „die Cloud“ bis vor etwa zwei Jahren eher ganz abgelehnt habe. (Unter „Cloud“ verstehe ich jetzt nur das Ablegen auf Servern von fremden Anbietern, insbesondere solchen bei denen ich nichts dafür zahle.)

Wie ich angefangen habe „die Cloud“ zu nutzen

Eine gewisse Akzeptanz für „die Cloud“ habe ich mit meinem Android-Telefon gewonnen. Wahrscheinlich gar nicht weil es besser war, aber es war wunderbar bequem Kontakte und Kalender bei Google abzulegen. Zuvor hatte ich hierfür vor allem SyncML benutzt, das auf meinem eigenen Server installiert war.

Mit der Zeit kamen weitere Dienste von Google dazu, die ich genutzt habe: Google Plus, Google News, Google Reader, Google Talk, Blogger und ja sogar Google Analytics.

Versuche Dienste wieder verstärkt auf meinem eigenen Server zu hosten

Ein gewisses Unbehagen meine Daten anderen anzuvertrauen, die irgendwie versuchen müssen damit Geld zu machen hatte ich auf jeden Fall aber. Seit vielleicht einem halben Jahr versuche ich deswegen beispielsweise wieder von Blogger weg zu kommen und eine Weblogging-Software auf meinem eigenen Server zu betreiben. Standard hierfür ist wohl WordPress. Allerdings ist dies in PHP geschrieben und der Server auf dem ich meine Sites laufen habe hat keine PHP-Runtime. Ich möchte eigentlich etwas in Java, weil ich damit sehr gute Erfahrungen habe was Beständigkeit, Administrierbarkeit und Skalierbarkeit habe. Ich arbeite deswegen mit Apache Roller. Testweise habe ich auch ein Blog darauf laufen und schon ein paar Bugreports (ROL-1958ROL-1956ROL-1955ROL-1952) abgegeben. So richtig rund ist die Sache für mich aber noch nicht: es fehlt mir die Möglichkeit mit sehr vielen Clients auf unterschiedlichen Plattformen darauf zugreifen zu können. Und ein hübsches Theme muss ich mir auch erst selbst basteln.

Noch schlimmer: ich habe mir vor ein paar Tagen sogar noch ein neues Blog bei Blogger angelegt und Inhalte einer bestehenden Website darauf konvertiert. Der Hintergrund ist, dass ich von meinem nächsten Segelurlaub aus per Android-Tablett offline Texte erstellen und dann wenn ich wieder Internet habe posten können möchte. Mit Blogger kein Problem, für Roller dagegen habe ich keinen passenden Client gefunden.

Google Reader wird eingestellt

Heute nun logge ich mich wie jeden Morgen in Google Reader ein um nachzusehen was sich in den von mir gelesenen Blogs so getan hat. Sofort poppt eine Nachricht von Google auf, dass Reader zum 1. Juli 2013 einstellt. Wirklich überraschend kam das zwar nicht. Gerechnet hatte ich irgendwie schon damit. Trotzdem hat mir das bewusst gemacht, wie sehr ich mich doch schon von solchen Produkten abhängig gemacht habe. Wie soll ich mir sicher sein, dass beim nächsten Mal nicht Blogger oder Talk abgeschaltet wird?

Konsequenzen für mich

Eines ist klar: ich will wieder mehr darauf achten meine Daten selbst auf meinem eigenen Server zu haben. Klar ist mir aber auch, dass ich nicht für jeden „Cloud“-Dienst sofort einen funktionierenden Ersatz habe. Ich habe für mich deswegen die folgenden Regeln aufgestellt:

  1. es ist okay einen Dienst in „der Cloud“ erst mal auszuprobieren und zu nutzen,
  2. „die Cloud“ ist prima damit ich mir anschauen kann was man so machen kann und ich mir nicht für alles sofort selbst eine Software installieren muss,
  3. aber wenn ein Dienst für mich beginnt wichtiger zu werden (oder besser noch davor), dann muss ich mir eine Alternative suchen, die ich selbst betreiben kann,
  4. ein „Cloud“-Dienst ist keine Dauerlösung für eine meiner Problemstellungen,
  5. eine Funktion aus mehreren Diensten zusammen zu setzen ist besser als ein Dienst, der alles integriert (ich kann die einzelnen Komponenten dann auch einzeln durch etwas bei mir ersetzen),
  6. einen Dienst für den ich angemessen bezahle ist besser als etwas werbefinanziertes (ich/meine Daten sind nicht die Ware, die verkauft wird, sondern ich bin der Kunde),
  7. meine Technologiewahlen sollen berücksichtigen, dass andere mit mir interagieren können, ohne dass sie auf einen speziellen Dienst angewiesen sind (z.B. RSS-Schnittstelle statt Google+/Facebook, XMPP statt ICQ/WhatsApp/Skype) und
  8. alles läuft auf Adressen (Domains), die mir gehören und die ich auch mit etwas anderem bestücken kann (z.B. keine Freemail-Adressen für E-Mail).

Nachtrag 20. März 2013, 13:51

Ähnliches Thema, interessanter Artikel:

„Nochmal: ‚Dein’ Facebook gehört dir nicht!” von Dr. Kerstin Hoffmann

http://www.kerstin-hoffmann.de/pr-doktor/2013/03/19/nochmal-dein-facebook-gehort-dir-nicht/

GSM-Modem SIM900 und GsmMuxd

posted on

Diese Woche habe ich an einer spannenden Aufgabenstellung gearbeitet: ich musste die Firmware für ein Gerät zur Datenerfassung und zum Monitoring an ein neues zukünftig darin verbautes GSM-Modem anpassen.

RemoteGuard mit GSM-Modem

Bisher wurde darin hauptsächlich das Modem SIM300 von SIMcom eingesetzt, mit der Anpassung soll auch das Nachfolgemodell SIM900 unterstützt werden, da das Vorgängermodell nicht mehr produziert wird.

Hardwaretechnisch war die Umstellung kein Problem. Das neue Modem konnte einfach anstatt des bisherigen eingebaut werden. Jedoch konnte die bestehende Firmware dem neuen Modem nicht viel entlocken. In unserem eigenen Logfile konnte ich nur einige Einträge finden, dass das Modem nicht reagieren würde.

Die Arbeit der Anpassung begannt mit dem Studium der Hinweise des Herstellers was sich im neuen Modem inkompatibel geändert habe. Hier wurde ich auch in bei ein paar AT-Kommandos fündig, die Anpassungen haben wollten. Mit den neuen Init-Skripten für das Modem meldete die Firmware nun immerhin schon, dass ein Modem gefunden wurde. – Ein schönes Zeichen, immerhin war damit schon mal bestätigt, dass hardwaretechnisch das Modem tatsächlich als Replacement dienen konnte. Der Rest, der nicht tat war Software und die lässt sich leichter anpassen.

Ich machte mich nun an die Arbeit die Kommunikation der Firmware mit dem Modem näher zu analysieren und stellte fest, dass die Probleme in der Implementierung des Protokolles 3GPP TS 07.10 liegen. Dieses Protokoll ist dafür zuständig mehrere virtuelle serielle Verbindungen über eine physikalische Verbindung zu übertragen. Dies ermöglicht es, dass das GSM-Modem nur über einen Seriellport angeschlossen wird, aber gleichzeitig per PPP auf einer virtuellen Verbindung ein Zugang zum Internet hergestellt wird während auf einer anderen virtuellen Verbindung noch immer beispielsweise AT-Kommandos zum Versand von SMS oder zur Abfrage der GSM-Signalstärke gemacht werden können. Für dieses Protokoll benutzen wir eine angepasste Version des Open-Source-Programmes GsmMuxd.

Etwas nach SIM900 und GsmMuxd gegooglt zeigte auch, dass es schon ein paar andere Entwickler gab, die anscheinend vor dem gleichen Problem standen. Allerdings hatte auf keiner der Seiten jemand davon berichtet, dass er das Problem lösen konnte, geschweige denn wie er das getan habe. Ich war also mal wieder auf meine eigenen Analysefähigkeiten angewiesen.

Ich habe mir ein paar Frames mitprotokolliert und anhand der Protokollspezifikation nachvollzogen. Sah soweit alles gut aus, die Frames waren gültig. Trotzdem verwarf GsmMuxd alle empfangenen Frames als ungültig:

if ((*data & 1) == 0) {
    /* Current spec (version 7.1.0) states these kind of frames to be invalid
     * Long lost of sync might be caused if we would expect a long
     * frame because of an error in length field.
    INC_BUF_POINTER(buf,data);
    frame->data_length += (*data*128);
    fcs = r_crctable[fcs^*data];
    length_needed++;
    */
    free(frame);
    buf->readp = data;
    buf->flag_found = 0;
    return gsm0710_buffer_get_frame(buf);
}

In diesem Stück Code in der Methode gsm0710_buffer_get_frame() in buffer.c wird das niederwertigste Bit in der Längenfeld des Frames geprüft. Dieses Feld kann ein oder zwei Byte lang sein und dieses Bit steuert eben genau die Länge des Feldes. Der bestehende Code von GsmMuxd erlaubt dabei nur eine Längenangabe mit einem Byte was einer maximalen Framelänge von 127 Bytes entspricht.
Im Gegensatz zum bisherigen SIM300-Modem überträgt das SIM900-Modem die Framelänge jedoch immer in 2 Bytes, auch wenn sie in einem Byte hätte dargestellt werden können.

Interessant in diesem Zusammenhang ist, dass im GsmMuxd der Code für die Dekodierung des zweiten Bytes bereits enthalten aber auskommentiert ist. Im Kommentar steht dazu, dass laut Version 7.1.0 der Spezifikation eine solche Längenangabe ungültig sei. Ich habe sowohl diese Version der Spezifikation wie auch die aktuelle eingehend danach untersucht, aber nichts gefunden was meiner Ansicht nach diese Annahme stützt. Vielmehr ist festgelegt, dass ein Frame nicht länger als „N1“ sein darf. Dies ist ein Wert, der optional von der Software beim Umschalten in den Multiplexmodus an das Modem übergeben wird. Wird dieser Wert nicht explizit übergeben, so gilt ein Defaultwert von 64. Da GsmMuxd nie einen expliziten Wert für „N1“ an das Modem übergibt, gilt also hier dieser Defaultwert. In der Tat ließe sich also die Framelänge immer in einem Byte übertragen. Aber es gibt keine Notwendigkeit dies auch zu tun. Ich denke, es ist deswegen sinnvoller erst auch ein zweites Byte der Längenangabe zu akzeptieren und danach die ermittelte Framelänge zu überprüfen:

if ((*data & 1) == 0) {
    /* Current spec (version 7.1.0) states these kind of frames to be invalid
     * Long lost of sync might be caused if we would expect a long
     * frame because of an error in length field.
     *
     * => I can't find this in the spec (either 7.1.0 or 7.2.0)
     * but we may check the length against N1. As we do not pass
     * N1 in the AT+CMUX command, we have the default which is 64.
     * (Matthias Wimmer, 20130207)
     */
    INC_BUF_POINTER(buf,data);
    frame->data_length += (*data*128);
    fcs = r_crctable[fcs^*data];
    length_needed++;
}
if (frame->data_length > 64) {
    free(frame);
    buf->readp = data;
    buf->flag_found = 0;
    return gsm0710_buffer_get_frame(buf);
}

Mit dieser Änderung war dann die Kompatibilität zum neuen Modem erreicht und ich um einen GSM/UMTS/…-Standard reicher, den ich gelesen habe.

Nachtrag 30. April 2013 15:12

Die letzten Tage habe ich ein Problem mit der Interneteinwahl und dem Modem festgestellt. Konkret konnte ich per PPP eine Verbindung zum Internet herstellen und darüber IP-Pakete verschicken. Ich habe jedoch nie ankommende IP-Pakete erhalten.

Beim Debugging bin ich auf das Problem gestoßen, dass das SIM900-Modem (und zwei andere getestete Modemes auch) entgegen dem Standard Frames mit einer Länge größer N1 geschickt hat. Diese werden durch den obigen Code (weiterhin) gedropped.

Es scheint mir, dass das SIM900 beim Senden der Frames N1 überhaupt nicht berücksichtigt. Bei einer üblichen MTU von 1500 Byte und einem PPP-Overhead von 6 Byte heißt das, dass Frames bis zu einer Länge von 1506 Bytes (anstatt der oben stehenden 64 Byte) akzeptiert werden sollten.

Auf was ich stolz bin: Unterschiede zwischen Latin 1 und Latin 9

posted on

Wieder einmal bin ich daran meine Website auf eine neue Plattform umzustellen. Eine Seite, die ich mit jeder Umstellung unangetastet liegen lasse ist meine Seite über die Unterschiede zwischen Latin 1 und Latin 9.

Nicht dass das eine so besonders wichtige Seite wäre. Glücklicherweise ist das Encoding der Wahl in der westlichen Welt inzwischen UTF-8 geworden. Aber ich bin stolz darauf, dass ich mit dieser Seite 2005 in der Musterlösung einer Übung der Universität Koblenz aufgetaucht bin: http://mtech.uni-koblenz.de/MT2005/Uebung/ueb1/loes1.pdf [PDF, 26 KiB].

Java Webstart und WELD

posted on

Für meinen Arbeitgeber habe ich ein Programm entwickelt, das wir nutzen Zeiten zu erfassen und in unser Projektmanagement einzukoppeln. Um in der Firma einfach auf allen Rechnern immer die neuste Softwareversion zur Verfügung zu haben, habe ich mich dafür entschieden Java Webstart einzusetzen. Diese Technik hatte ich auch bereits für einige andere Java-Anwendungen von meinen Kunden eingesetzt.

Neu dieses mal war nun allerdings, dass ich nicht Spring sondern CDI für die Dependency Injection gewählt habe. CDI implementiert durch WELD ist bei uns auf der Arbeit hierzu meist der Standard der Wahl.

Das Problem als ich die fertige Anwendung deployen wollte

Die Entwicklung lief soweit streight-forward. Allerdings habe ich die Anwendung zum Testen nicht wirklich auf einen Webserver gestellt sondern in meinem lokalen Dateisystem installiert. Alle URLs im Webstart-Deskriptor waren deswegen der Art file:///home/matthias/source/zeiterfassung/… und funktionierten super. Die Ernüchterung kam erst als ich die Anwendung mit der endgültigen URL deployen wollte. Als Web-URL beginnt diese natürlich mit https://… und zu meinem Erschrecken macht das WELD Probleme:


Fehlermeldung/Exception in der Java-Konsole

WELD holt sich anscheinend die URL der Java-Archive vom Classloader um darin suchen zu können und der Classloader liefert für die Archive, obwohl er sie schon heruntergeladen hat die Originaladressen mit http://- oder https://-Präfix. Allerdings geht WELD davon aus, dass die URLs auf lokale Dateien zeigen. Bumm, es fliegt eine Exception und nichts startet.

Dokumentiert ist dieser Fehler seit einem guten Jahr als Bugticket WELD-1040 eine Bugfixrelease gibt es dafür jedoch noch nicht.

Workaround

Was tun, wenn ich die Anwendung zum Laufen bekommen will? Im Bugreport ist ein „proposed Fix” enthalten. Mir gefällt dieser Fix nicht wirklich. Es wird hier im FileSystemURLHandler von WELD einfach geschaut, ob eine URL mit „http:” oder „https:” beginnt und in diesem Fall die URL gegen die URL der gecachten Kopie im lokalen Dateisystem ausgetauscht. Das ganze funktioniert so nur ab Java 6, behebt nicht das eigentliche Problem, dass WELD nur spezielle URLs („file:”) versteht und hat sowieso keinerlei Fehlerbehandlung.

Aber gut, da die Anwendung im Moment nur von uns intern genutzt wird und sowieso Java 7 voraussetzt, habe ich mir die Sourcen von WELD besorgt, den Patch eingespielt nur mir selbst Pakete dafür gebaut.

Bleibt zu hoffen, dass der Fehler bald richtig und in einer offiziellen Release behoben wird. Immerhin ist im Bugticket „Fix Version/s: 2.0.0.CR1” gesetzt, das lässt hoffen.

Anmerkung: Wer im Bild oben genau hinschaut sieht, dass aus der URL http://example.com/ tatsächlich http:/example.com/ gemacht wird. Das ist kein Tippfehler in meinem Deskriptor sondern Teil des Verhaltens der ungepatchten Version.

Bericht von der Prüfung DELE Nivel A1

posted on

Heute mal etwas ganz anderes hier als sonst: ein Erfahrungsbericht von meiner DELE-A1-Prüfung Anfang November beim Instituto Cervantes Múnich.

DELE sind die offiziellen Prüfungen des spanischen Kultusministeriums über Spanisch als Fremdsprache. Es gibt die Prüfungen in den sechs Stufen des Gemeinsamen Europäischen Referenzrahmens. A1 ist dabei die kleinste Stufe. Ganz grob gesagt ist A1 etwa das Niveau, das man nach einem Schuljahr Fremdsprachenunterricht (zwei Stunden pro Woche) erreicht. C2 ist die höchste Stufe und ist das Niveau, wenn man fast wie ein Muttersprachler spricht. Meine Stufe würde ich deswegen umschreiben als „zertifiziertes nichts können”.

Prüfungsbeginn

Die Prüfung hat um 9:00 Uhr begonnen. Wir sollten allerdings schon eine halbe Stunde früher im Instituto Cervantes erscheinen. Dort mussten wir dann im Eingangsbereich am Empfang warten bis wir aufgerufen wurden. Pünktlich um 9 wurden alle zehn Prüflinge für A1 dann zusammen aufgerufen und zu unserem Prüfungsraum geführt. In diesen wurden wir dann einzeln eingelassen, dabei wurde jeweils unser Ausweis kontrolliert. Im Raum waren unsere Plätze schon vorbereitet. An jedem Platz lag ein Bleistift, ein Radiergummi und ein Spitzer. Ein Namensschild mit unserer Nummer war auf den Tisch geklebt, ein Datenblatt mit unseren persönlichen Daten  und der Aufgabenbogen mit den Aufgaben für die ersten beiden Teilprüfungen (Leseverstehen und Hörverstehen) lag bereits auf dem Tisch. An jedem Tisch saßen sich an den kurzen Seiten zwei Prüflinge gegenüber.

Eine sehr freundliche Frau hat uns auf deutsch noch einmal den Ablauf des Tages erklärt und uns gebeten das Datenblatt zu kontrollieren. Die darauf aufgedruckten Daten würden so auch in unser Diplom gedruckt und hätten jetzt noch korrigiert werden können. Auch alle weiteren Erklärungen wurden uns auf deutsch gegeben.

Teilprüfung Leseverstehen

Uns wurde jetzt auch der Ablauf der ersten Teilprüfung (Leseverstehen) erklärt und daraufhin der Lösungsbogen ausgeteilt. Als dieser ausgeteilt war hatten wir für den ersten Prüfungsteil 45 Minuten Zeit. Er besteht aus vier einzelnen Aufgaben, die immer eine ähnliche Struktur haben. Es gibt im Buchhandel auch mehrere Bücher mit Beispielprüfungen, die genau zeigen was für Fragen hier gestellt werden.

Alle Lösungen waren in dem ausgeteilten Lösungsblatt einzutragen. Man durfte aber auch im Aufgabenblatt schreiben und sich dort Notizen machen. Diese zählen jedoch nicht in der Korrektur (weder positiv noch negativ). Bewertet wird nur was auf dem Lösungsbogen steht. Am besten streicht man sich bei Aufgaben, bei denen man Zuordnungen machen muss, die schon benutzten Elemente durch. Gerade im zweiten Prüfungsteil, in dem man hören muss, hilft es sehr, wenn man bei folgenden Auswahlen nur noch zwischen weniger Möglichkeiten aussuchen muss.

Der Lösungsbogen wird maschinell ausgewertet. Auf ihm hat es für jede Antwortmöglichkeit bei einer Multiple-Choice-Frage einen Kreis. Man muss den jeweils korrekten immer ganz ausmalen. Möchte man seine Antwort ändern, darf man die bisherige nicht durchstreichen sondern muss diese ausradieren. Lediglich beim Lückentext war jeweils ein ganzes Feld für das jeweilige Lösungswort vorhanden.

Teilprüfung Hörverstehen

Als die ersten mit den Aufgaben des ersten Prüfungsteiles fertig waren, hat man uns den Tipp gegeben, dass wir gerne auch schon die Antworten der zweiten Teilprüfung (Hörverstehen) anschauen können. Indem man sich die möglichen Antworten anschaut, kann man sich schon etwas auf die möglichen Fragen vorbereiten.

Nach Ende der ersten Teilprüfung ging es umgehend mit der zweiten Teilprüfung los. Pausen gab es zwischen den ersten drei Teilprüfungen keine. Die anwesende Prüferin hat uns wieder erklärt was wir tun müssen. Das Antwortblatt der zweiten Teilprüfung wurde ausgeteilt und das der ersten Teilprüfung wieder eingesammelt.

Dieser zweite Teil dauert zwanzig Minuten und lief komplett von CD. Hier gab es auch noch mal die Erklärung des Prüfungsteils auf spanisch zu hören und die Aufgabenstellungen wurden genannt. Diese stehen aber auch schriftlich im Aufgabenblatt. Es gibt in dieser Teilprüfung wieder vier Aufgaben. Geprüft wird in diesem Teil, ob man versteht was man hört. Auch diese Prüfungen sind in den Büchern mit Beispielprüfungen sehr gut wiedergegeben. Ganz besonders gut hat mir zur Vorbereitung übrigens das Buch „El cronómentro” von Edinumen gefallen. In diesem Buch ist der zweite Prüfungsteil am realistischsten wiedergegeben indem die Audiodateien auf der CD wie in der Prüfung alle Texte wiederholen und Pausen wie in der realen Prüfung aufgezeichnet sind. In den anderen Prüfungsbüchern wurde in den Audiodateien alle Texte nur einmal vorgelesen und keine Pausen dazwischen gemacht.

Teilprüfung schriftlicher Ausdruck

Im dritten Teil geht es darum kurze Texte schreiben zu können. Es wurde ein neuer Lösungsbogen für diesen Prüfungsteil ausgeteilt, der dieses mal auch direkt die „Fragen” enthalten hat. Der Lösungsbogen für den zweiten Teil wurde eingesammelt. Die erste Aufgabe auf dem Lösungsbogen war ein Formular, das auszufüllen war. Es ging darum eine Wohnung zu verkaufen und hierfür eine Anzeige aufzugeben. Neben einigen Feldern, die auszufüllen waren, sollte man lediglich noch in zwei Zeilen die Wohnung beschreiben.

Die zweite Aufgabe war es eine E-Mail an eine Gastfamilie zu schreiben. Welche Informationen man in die E-Mail schreiben soll war dabei in der Aufgabenstellung vorgegeben. Die E-Mail sollte zwischen zwanzig und dreißig Wörtern lang sein. Bearbeitungszeit für beide Aufgaben zusammen fünfundzwanzig Minuten.

Im Anschluss an die dritte Teilprüfung begannen sofort die mündlichen Prüfungen des vierten Prüfungsteils. Da diese Prüfungen einzeln stattfinden und ich der vorletzte Prüfling war, hatte ich jedoch etwas Pause und konnte etwas nach Hause fahren.

Mündliche Prüfung

In der mündlichen Prüfung geht es darum herauszufinden, ob der Prüfling sich einfach mündlich ausdrücken und verständigen kann. So wie ich dies erlebt habe war dabei das wichtigste, dass man mit dem Prüfer über einfache Themen kommunizieren kann. Ob dabei immer die Grammatik eingehalten wurde war zweitrangig wenn die Kommunikation lief. Jedenfalls ist mir selbst beim Sprechen aufgefallen, dass immer mal wieder eine Verbendung falsch war oder ich das falsche Geschlecht benutzt habe. Dies wurde nicht korrigiert. Auch ist mir einmal keine Vokabel für den Kopf eingefallen und ich bin dann kurz in eine Geste übergegangen. Der Prüfer hat mir dann geholfen, indem er nachfragte, ob ich den Kopf meine. Das konnte ich dann einfach bestätigen und hatte damit gleichzeitig auch das spanische Wort.

Für die mündliche Prüfung hatte ich erst fünfzehn Minuten Vorbereitungszeit. In dieser konnte ich die ersten zwei von vier Teilaufgaben vorbereiten. Zum einen war das (und ist vermutlich in jeder Prüfung), dass man sich selbst vorstellt. Zur Vorbereitung erhält man eine Liste mit Dingen die man erwähnen könnte.

Die zweite Aufgabe ist prinzipiell das gleiche, nur dass man über ein anderes Thema etwas erzählt. Man durfte sich in der Vorbereitung eines von fünf Themen aussuchen und hatte dann dazu auch eine Liste von Dingen, die man erwähnen kann.

Nach der Vorbereitung ging es in einen Raum mit dem Prüfer und einer Schriftführerin. Der Prüfer hat sich und die Schriftführerin gleich auf Spanisch vorgestellt und mich begrüßt, so dass wir direkt im Gespräch angekommen waren und ich mich vorstellte. Ich glaube, dass es dabei auch gut war auf das was der Prüfer sagte immer versuchen zu reagieren. („Enchantado”, „¡Qué interesante!” und so weiter …)

Die vier Aufgaben wurden dabei gar nicht wirklich einzeln geprüft sondern waren mehr die Aufhänger anhand derer sich unser Gespräch entwickelt hat.
Die dritte und vierte Aufgabe war anhand von Bildern Fragen zu beantworten (3. Aufgabe) und zu stellen (4. Aufgabe). Zu jeder Aufgabe hat sich der Prüfer zwei Bilder aus einem Stoß von Karten ausgewählt. Die Fragen waren dabei viel einfacher als ich das vorher erwartet hatte:
1. Karte: Bild von einer Person, die gerade im Bett liegt und einen Wecker ausschaltet. Ich werde gefragt um wie viel Uhr diese Person aufsteht. Als Antwort muss ich nur die Uhrzeit vom Wecker ablesen und nennen.
3. Karte: Bild von einer Bedienung in einem Restaurant. Frage an mich war was diese Frau arbeitet. (Meine Antwort, dass sie in einem Restaurant arbeitet ­– anstatt einer Berufsbezeichnung –, war okay.) Anschließend daran die Frage, ob mir dieser Beruf auch gefallen würde.
4. Karte: Bild von einem Kalender, ein Datum ist angestrichen. Ich werde gefragt welches Datum dies ist. Außerdem soll ich sagen, wie ich nach dem Datum von heute fragen würde.

Prüfungsergebnis

Das Ergebnis der mündlichen Prüfung wurde mir sofort am Ende der mündlichen Prüfung mitgeteilt. Auf das Ergebnis der ersten drei Prüfungsteile muss ich jedoch etwa drei Monate warten. Das dauert so lange, da diese zentral in Spanien korrigiert werden.

DHL datiert Status der Zustellung in die Packstation zurück

posted on

Mehr als eine Woche warte ich auf eine Sendung von Amazon. Ich habe sie mir an die Packstation schicken lassen.

Samstag, 25. August 2012: Die DHL-Sendungsverfolgung meldet: „Diese Sendung befindet sich auf dem Weg zur Packstation.“ Weiter ist nichts passiert.

Ein paar Tage später: Ich reklamiere die Sendung bei Amazon. Die Kundenbetreuung wundert sich auch wo das Paket steckt. Sie schicken die Bestellung ein zweites Mal los.

Donnerstag, 30. August 2012: DHL meldet auch für das zweite Paket: „Diese Sendung befindet sich auf dem Weg zur Packstation“ und es tut sich weiter nichts.

Diese Packstation steht vorübergehend nicht zur Verfügung

Mittwoch, 29. August 2012: Ich bin genervt aber habe die Hoffnung, die SMS könnte nur nicht angekommen sein. Vielleicht kann ich das Paket abholen. Leider nein! Dafür weiß ich was los ist, denn auf dem Bildschirm der Packstation steht: „Diese Packstation steht vorübergehend nicht zur Verfügung.“ Kann passieren, aber wieso geht die Sendung dann nicht in die Postfiliale nebenan oder an eine andere Packstation?

Die Sendungsverfolgung bringt mich zum Staunen

Montag, 3. September 2012: Ich habe lange gewartet, jetzt ist es soweit. Ich bekomme als info eine SMS und eine E-Mail.
Richtig interessant ist nun aber der Blick in die Sendungsverfolgung: DHL hat den Status für die Zustellung zurückdatiert. Sie behaupten, die erste Sendung sei am 25. August um 10:42 Uhr in der Packstation angekommen, die zweite am 30. August um 13:03 Uhr.

Wer weiß, vielleicht funktionierte die Packstation noch als das erste Paket deponiert wurde. Sie könnte kaput gegangen sein bevor sie den Status per SMS und E-Mail übermittelt hat. Aber auch wenn dem so wäre: zum zweiten Zeitpunkt war sie definitiv nicht mehr in Betrieb!

Das ist eine Frechheit. Es dauert über eine Woche mir das Paket irgendwie zugänglich zu machen. Aber der Status wird einfach frech zurückdatiert als sei alles korrekt gelaufen. Ich frage mich, ob man das nicht Urkundenfälschung nennen muss.

Zur Dokumentation ein paar Screenshots von diesem Vorfall

1. Sendung

Tatsächlich war die Sendung am 3. September in der Packstation abholbereit, laut Tracking aber schon am 25. August.

Mit einer SMS am 3. September um 8:26 Uhr hat mich die Packstation informiert, dass die Sendung bereit ist.

2. Sendung

Auch die zweite Sendung war tatsächlich erst am 3. September in der Packstation zur Abholung und nicht wie von DHL behauptet am 30. August.

SMS von der Packstation, die mich am 3. September um 13:07 Uhr informiert, dass die Sendung bereit ist.

Auch per E-Mail wurde erst am 3. September informiert.

Apps für Android 4 fit machen

posted on

Im Play-Store gibt es einige Apps zur Vorbereitung auf Funk- und Sportbootführerscheine von mir. Um eine möglichst große Zahl von Nutzern zu erreichen, habe ich die Anwendungen kompatibel zu Android 2.1 entwickelt. – Für mich hieß das, dass ich bei der Erstellung für die Anwendungen das API-Level 7 als „Project Build Target“ benutzt habe.

Ergebnis dieser Vorgehensweise ist, dass auch Telefone mit einer neueren Version von Android die Anwendung in einer Art „Kompatibilitätsmodus“ ausführen. In diesem Modus wird die ganze Oberfläche möglichst genau so gezeichnet wie es unter der alten Version der Fall war. Dies soll sicherstellen, dass auch eine Anwendung, die sich z.B. genau darauf verlässt wie groß ein Button zu sein hat auch Buttons in genau dieser Größe vorfindet.

Schauen wir uns das ganze zuerst in Bildern an:

Android-2.1-kompatibler Modus von Jelly Beans (Android 4.1)

Originäre Darstellung auf Jelly Beans (Android 4.1, Telefon mit Hardwaretasten)

Die Unterschiede hier sind:

Die notwendigen Änderungen damit neuere Android-Versionen nicht in den Kompatibilitätsmodus schalten sind minimal und benötigen keine einzige Änderung am Programmcode. Lediglich ein paar Änderungen in den XMLs der Anwendung sind notwendig.

AndroidManifest.xml

Die wichtigste Änderung, die vorzunehmen ist, befindet sich in der Datei AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="eu.wimmerinformatik.sbfs"
    android:installLocation="auto"
    android:versionCode="5"
    android:versionName="1.4" >

    <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="16" />

    <application
        android:icon="@drawable/ic_launcher_sbfs"
        android:label="@string/app_name" >
        <activity
            android:name=".SBFSTrainerActivity"
            android:label="@string/app_name" >

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity
            android:name="eu.wimmerinformatik.sbfs.QuestionAsker"></activity>

        <activity
            android:name=".StatisticsActivity"></activity>
    </application>
</manifest>

Die hier wichtige Änderung ist das android:targetSdkVersion="16". Diese Angabe bedeutet, dass die Anwendung bis SDK Release 16 (= Android 4.1) getestet ist und keine Kompatibilitätseinstellungen für ältere Android-Versionen benutzt werden müssen. Diese Änderung sorgt dafür, dass Android ab Version 3.0 das Holo-Theme für die Darstellung der Anwendung nutzt. D.h. die neuen Widgets werden benutzt und das App-Icon erscheint in der Action-Bar, die überhaupt erst hiermit aktiviert wird.

Menü-XML-Dateien

Eine weitere Änderung ist in den XML-Dateien, die die Menüs der Anwendung definieren notwendig:

<?xml version="1.0" encoding="utf-8"?>

<menu
    xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/statistics"
        android:visible="true"
        android:title="@string/menuStatistics"
        android:enabled="true"
        android:showAsAction="ifRoom"
        android:icon="@drawable/ic_statistics"></item>

    <item
        android:id="@+id/resetTopic"
        android:title="@string/menuResetTopic"
        android:titleCondensed="@string/menuResetTopicCondensed"
        android:visible="true"
        android:enabled="true"
        android:showAsAction="never"></item>

</menu>

Neu hier eingefügt sind die Attribute android:showAsAction. Mit diesem Attribut und dem Wert „ifRoom“ habe ich festgelegt, dass ich den Menüeintrag für die Statistik gerne direkt in der ActionBar sehen würde (wenn Platz dafür ist). Mit dem Wert „never“ lege ich fest, dass der Menüeintrag zwar fit für neuere Android-Versionen ist, aber nicht direkt in der ActionBar angezeigt werden soll.

Eclipse-Einstellung

Zuletzt muss noch Eclipse gesagt werden, dass es die neuen Einträge in den XML-Dateien auch akzeptiert. Hierzu werden im Kontextmenü des Projektes die Properties ausgewählt. Auf dem Tab „Android“ wird als „Project Build Target“ „Android 4.1“ ausgewählt.

Die App wird damit jetzt mit dem SDK für Jelly Beans übersetzt, das die neuen Einträge im XML kennt und verarbeiten kann. Da in der AndroidManifest.xml als minSdkVersion die 7 angegeben ist, entsteht jedoch eine APK-Datei, die auch von älteren Android-Versionen akzeptiert wird.

Achtung, diese Einstellung bewirkt, dass der Compiler einen nicht mehr aufhält, wenn man Klassen nutzt, die nicht auf allen Android-Versionen, die man unterstützen möchte vorhanden sind. Der Programmierer ist jetzt selbst dafür verantwortlich sicherzustellen, dass die App unter allen als kompatibel markierten Android-Versionen auch wirklich auffähig ist. Das heißt: es wird noch viel wichtiger, dass man die App vor der Veröffentlichung gut testet und diese Tests unter verschiedenen Android-Versionen auszuführen.

Kompatibilität von 8192-Bit-Zertifikaten

posted on

Aufgrund der Tatsache, dass die Hardware mit denen Public-Key-Schlüssel angegriffen werden kann immer leistungsfähiger wird, ist es notwendig, dass auch die Größe der eingesetzten Schlüssel immer weiter vergrößert wird.

Für den Einsatz mit qualifizierten digitalen Signaturen in Deutschland veröffentlicht beispielsweise die Bundesnetzagentur jährlich den sogenannten Algorithmenkatalog. In ihm steht jeweils welche Mindestschlüssellänge bis zu welchem Zeitpunkt als ausreichend angesehen werden kann.

Aktuell wird für den Einsatz von RSA-Schlüsseln bis Ende 2018 beispielsweise empfohlen, dass diese mindestens 2048 Bit lang sein sollten.

Dies betrifft aber natürlich nicht nur qualifizierte Signaturen sondern beispielsweise auch die verschlüsselte Übertragung von Webseiten mit dem HTTPS-Protokoll. Auch hierfür werden meistens RSA-Schlüssel eingesetzt. Üblicherweise trifft man auf Webservern dabei meistens Schlüssel der empfohlenen Länge an. (Ergebnis einer nicht repräsentativen Überprüfung einiger Websites durch mich.)

Natürlich kann man aber auch längere Schlüssel erzeugen und genau das habe ich gemacht bevor ich mir mein letztes Zertifikat habe ausstellen lassen. Der zugehörige RSA-Schlüssel ist 8192 Bit lang. Sicher eine an sich zur Zeit noch übertriebene Schlüssellänge, aber ein interessanter Key um damit zu testen ob alle Browser mit Keys dieser länge umgehen können.

ChromeFirefoxInternet Explorer 9Opera 12Safari 6
Linux (Debian wheezy)OKOK-OK-
Mac OS X (10.8)Meldung „Ungültiges Serverzertifikat“. Fehler kann nicht ignoriert werden.OK-OKLaden der Seite hängt, keine Fehlermeldung
Windows 7OKOKOKOK- (Safari 5: OK)

Wer sicherstellen möchte, dass seine Seite problemlos von allen Nutzern angeschaut werden kann, sollte zur Zeit also noch keine 8192-Bit-Schlüssel einsetzen, da er ansonsten einen Großteil von Mac-OS-X-Nutzern ausschließt.


Fehlermeldung von Chrome unter Mac OS X 10.8.1

TODO: Es interessiert mich noch, wie es mit älteren Versionen von Windows aussieht. Ich habe es noch nicht getestet, aber es könnte sein, dass es unter Windows XP anders aussieht als unter Windows 7.

Site schnellstens aus Google entfernen: alles außer robots.txt sperren

posted on

Diese Woche bekomme ich einen Anruf von einem Bekannten: er entwickelt gerade eine Website für einen Kunden. Und obwohl die Seite noch nicht fertig ist, taucht sie schon im Suchindex von Google auf. Er hatte vergessen die Seite während der Entwicklung mit einem Passwortschutz zu versehen. Er fragte mich, ob ich eine Idee habe, wie er dieses Versäumnis so schnell als möglich korrigieren könne.

Wir sind nun gemeinsam ein paar Möglichkeiten durchgegangen das Problem zu beheben:

  • Site jetzt mit Passwortschutz versehen: es kommt zwar niemand mehr auf die Seite, allerdings ist sie noch in Google (und vermutlich anderen Suchmaschinen) gelistet,
  • robots.txt auf die Seite laden, die allen Suchmaschinen sagt, dass die Site nicht gelistet werden möchte: wer die Adresse kennt kommt trotzdem noch darauf oder
  • manuell über die Google Webmaster-Tools die Löschung beantragen: allerdings hatte Google schon über 10.000 Treffer auf der Site.

Alle drei Einzelmaßnahmen alleine reichen nicht aus. Wir haben uns entschlossen, dass alles drei in Kombination sinnvoll ist. Eine kleine Herausforderung war nun den Webserver so zu konfigurieren, dass alle Seiten der Site grundsätzlich mit einem Passwortschutz versehen waren, als einziges der Zugriff auf die Datei robots.txt jedoch ohne Passwort möglich war. Meistens wird ein Passwortschutz ja über einen Eintrag wie "require valid-user" in einer .htaccess-Datei eingerichtet. In diesem Fall hätte ein solcher Schutz allerdings ins Root-Verzeichnis der Domain gelegt werden müssen und die robots.txt wäre dann auch nicht mehr abrufbar gewesen.

Lösen lässt sich dieses Problem mit der <LocationMatch>-Einstellung von Apache und einem kleinen regulären Ausdruck:

<LocationMatch "^/(?!robots\.txt).|robots\.txt.+$">
    require valid-user
    AuthType Basic
    AuthUserFile /etc/apache2/users/.htuser
    AuthName Devel-Area
</LocationMatch>

Eingetragen kann dies allerdings nicht in eine .htaccess-Datei werden. <LocationMatch> ist in einer solchen Datei nicht zulässig. Der Eintrag muss in den vhost-Eintrag der Apache-Konfiguration gemacht werden (unter Debian: /etc/apache2/sites-available/*).

Auf diesem Weg konnten wir den Zugriff auf die Seite sofort sperren und trotzdem den Suchmaschinen ermöglichen die Datei robots.txt zu lesen. Da diese Datei von Suchmaschinen häufig angefragt wird und wir darin die komplette Indizierung der Site gesperrt haben, waren so auch die Einträge in Google auch innerhalb von ein paar Stunden wieder Vergangenheit.

Probleme mit TLS-Verbindungen bei StartSSL-Zertifikaten

posted on

Ich greife mit zwei E-Mail-Programmen auf meinen Mailaccount zu. Das eine ist mutt, das andere ist Thunderbird. Während ich mit mutt keine Probleme habe, kann ich seit zwei Tagen mit Thunderbird nicht mehr auf mein E-Mail-Konto zugreifen.

Wenn ich es probiere, dann sehe ich Thunderbird für etwa 20 Sekunden versuchen eine Verbindung mit dem Mailserver aufzubauen. Nach diesen 20 Sekunden stellt sich Thunderbird wieder so als hätte es nicht versucht E-Mails abzufragen. Es kommt also auch keine Fehlermeldung oder dergleichen.

Da ich meinen Mailserver selbst betreibe, habe ich auch die Gelegenheit in dessen Logfile zu schreiben. Besonders aussagekräftig ist der Eintrag dort allerdings auch nicht:

Jul 11 22:30:24 eder imapd: couriertls: read: error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate

Das heißt so viel wie „der Client hat uns gesagt, dass er unser Zertifikat nicht akzeptiert, mehr weiß ich auch nicht“.

Ich habe eine ganze Zeit gesucht an was es liegen könnte, dass mein Thunderbird das Zertifikat des Mailservers nicht mehr akzeptiert. Des Rätsels Lösung ist, dass ich Thunderbird so eingestellt habe, dass er jedes Zertifikat bei der jeweiligen Zertifizierungsstelle (in meinem Fall StartSSL) überprüft, ob es inzwischen zurückgezogen wurde. Hierzu gibt es das Protokoll OCSP (Online Certificate Status Protocol).

Screenshot von den OCSP-Einstellungen meines Thunderbirds.
OCSP-Einstellungen von Thunderbird. Zu erreichen über Einstellungen > Erweitert > Zertifikate > Validierung

Hier liegt auch das aktuelle Problem: StartSSL scheint aktuell nicht in der Lage zu sein OCSP-Anfragen zu beantworten. Und eine weitere Einstellung in meinem Thunderbird sagt diesem: „Wenn eine OCSP-Server-Verbindung fehlschlägt, das Zertifikat als ungültig betrachten“. Soweit ich weiß, ist diese Einstellung per Default in den Mozilla-Produkten ausgeschaltet. Ich halte dies jedoch für keine gute Idee, da auf diesem Weg von einem Angreifer sehr einfach eine Überprüfung eines ggf. gestohlenen Zertifikates über OCSP verhindert werden kann. Er müsste nur dafür sorgen, dass kein Connect zum Zertifikatsherausgeber mehr gelingt. Diese Einstellung abzusichern ist bei der Konfiguration von Thunderbird also immer eines der ersten Dinge die ich mache.

Auch jetzt habe ich mich dazu entschlossen, dass ich diese Einstellung in meinem Mailprogramm nicht lockere sondern stattdessen besser vorübergehend auf den Einsatz von Thunderbird verzichte und all meine E-Mails mit mutt lese. Man könnte zwar nun sagen, dass dieser aktuell ja auch nur funktioniert, da er keiene OCSP-Überprüfung durchführt. Allerdings läuft mein mutt auf dem gleichen Server wie auch mein Mailserver. Da aller Traffic nur über das loopback-Device läuft habe ich hier geringere Sorgen auf diesem Weg angegriffen zu werden. Wenn jemand in der Lage ist diese IP-Pakete zu modifizieren, dann hat er solchen Zugriff auf den Server, dass er sich diese Mühen nicht mehr machen muss. Er verfügt dann ohnehin über mehr Möglichkeiten.

Was man an der ganzen Erfahrung eigentlich am Meisten enttäuscht ist, dass mir Thunderbird keine Fehlermeldung ausgibt. Ein Hinweis, dass die OCSP-Abfrage beim Herausgeber des Zertifikates nicht möglich war und er das Zertifikat des Servers deswegen ablehnt, hätte mir viel Problemsuche erspart. Oder zumindest nur eine Ausgabe, dass das Zertifikat ungültig sei, hätte mir zumindest die Suche nach dem Grund dafür erleichtert. Ich habe einen Bug hierzu bei Thunderbird aufgemacht. Vielleicht baut ja jemand eine entsprechende Fehlermeldung in zukünftige Versionen ein.

Mein Dank geht übrigens an Milan Berger, er hat mich mit seinem Blogpost OCSP, StartSSL und Performanceeinbußen auf den richtigen Weg gebracht die Ursache zu finden.

Nachtrag 12. Juli 2012, 10:00

Aktuell scheint der OCSP-Responder von StartSSL wieder zu funktionieren. Thunderbird akzeptiert das Zertifikat meines Mailservers wieder.

Android 4.0.3+ überholt Version 2.3.3+

posted on

Diese Woche hat für die erste meiner Anwendungen (SKS-Trainer) die Anzahl der Installationen auf Android 4.0.3+ die der Installationen auf Android 2.3.3+ überholt. Bei meinen anderen Apps – vor allem denen für die Funkscheine – hat letztere die Nase noch vorn. Nach den Zahlen von Google ist Android 2.3.3+ auch an sich noch immer die am häufigsten genutzte Version des Handybetriebssystems.

Ich biete fünf Android-Apps im Play Store an. All diese Programme richten sich an annähernd die gleiche Zielgruppe: Anwender, die sich auf einen Segelschein vorbereiten und die Theoriefragen lernen wollen.

VersionDurchschnitt lernenSportboot binnenSKSUBISRCLRC
Android 2.3.3+56,61 %45,1 %40,7 % 42,0 %45,5 %49,5 %
Android 2.215,51 %7,5 %6,6 % 9,0 %7,5 %8,0 %
Android 4.0.3+15,23 %38,7 %41,5 % 33,5 %32,0 %29,0 %
Android 3.25,72 %6,2 %9,0 % 13,0 %12,0 %12,0 %
Android 2.13,87 %1,7 %0,9 % 1,5 %1,0 %1,5 %
Android 3.12,36 %0,5 %0,9 % 0,5 %1,0 %
Android 2.30,32 %0,1 %0,1 %
Android 4.00,14 %0,1 %0,1 % 0,5 %
Android 3.00,13 %0,1 %0,1 % 0,5 %

In vorstehender Tabelle befinden sich die Android-Versionen nach denen Google die Verteilung unterscheidet. Ich habe dabei nur die Versionen berücksichtigt auf denen meine Anwendungen lauffähig sind. (Android 1.5 und 1.6 hätten zusammen einen Anteil von 0,62 % im Play-Store in der Kategorie „Lernen“.)

In der Spalte „Durchschnitt lernen“ steht die Verteilung der Android-Versionen wie sich durchschnittlich bei Anwendungen vorkommt, die in den Bereich „Lernen“ einsortiert sind. In den anderen Spalten stehen die Verteilungen für die Verschiedenen Apps von mir.

Screenshot aus der Play-Konsole, der die Verteilung auf Android-Versionen
darstellt.
Verteilung der Installationen meines SKS-Trainers auf Android-Versionen

An meinen Zahlen fällt dabei auf, dass ich einen deutlich überdurchschnittlichen Anteil von Nutzern habe, die meine Anwendungen mit Android 3.0 oder höher nutzen (Tabletts und neuere Mobiltelefone). Mein Anteil an Nutzern mit älteren Versionen dagegen ist unterdurchschnittlich.

Woher könnte dies kommen? Nun zuerst ist festzustellen, dass die Anteile die Google für den Play-Store ermittelt weltweit ermittelt werden. Meine Apps dagegen richten sich fast ausschließlich an Nutzer in Deutschland, da damit auf deutsche Segelscheine gelernt wird. Außerdem ist festzustellen, dass meine Apps natürlich mit Seglern (und Motorbootfahrern) eine thematisch deutlich eingeschränktere Zielgruppe ansprechen. Als dritten Grund könnte man noch annehmen, dass meine Apps überhaupt erst seit unter drei Monaten verfügbar sind. In die allgemeine Statistik von Google zählen dagegen auch Programme, die auf älteren Geräte installiert wurden, die inzwischen ungenutzt in irgendeiner Schublade liegen.

Meine Zahlen für meine Apps von oben beziehen sich übrigens auf derzeit knapp 5.000 Installationen. Mit Abstand am meisten installiert sind die Anwendungen auf dem Samsung Galaxy S2 (knapp 20% der Installationen). Für dieses Gerät gab es ursprünglich Android in der Version 2.3, seit Februar 2012 gibt es Version 2.3.6 und seit April ist Android 4.0.3 für dieses Gerät als Update verfügbar.

Virtuelles Hosting für HTTPS mit Apache und mod_gnutls

posted on

Die IPv4-Adressen gehen aus – so ließt man. Im Februar 2011 wurde die letzte freie Adresse in Europa vergeben. Was seitdem getan wird: nichts. Trotzdem leiste ich meinen Beitrag: ich spare IPv4-Adressen mit virtuellem Hosting auch für HTTPS.

HTTPS und die IP-Adressen

Der wichtigste Grund warum ein Webserver mehrere IP-Adressen hat ist HTTPS. Für jede HTTPS-Domain brauchte man bisher eine eigene IP-Adresse. Die Verschlüsselung von HTTPS wird aktiviert bevor der Webbrowser dem Server sagt welche Webadresse er abrufen möchte. Das Problem dabei: das Zertifikat welcher Domain soll der Server nun benutzen? Verwendet er das falsche meckert der Browser. Eine rote Seite erscheint und warnt den Internetnutzer, dass da etwas nicht stimmt und die Seite vielleicht unsicher ist. Das wollen wir nicht!

Die Lösung bisher: jede Domain hat eine eigene IP-Adresse. Muss ein Webserver eine HTTPS-Anfrage beantworten, schaut er welche IP-Adresse angesprochen wurde. Kein Problem, das kann er. Für jede IP-Adresse weiß er die zugehörige Domain. Er kann das richtige Zertifikat nutzen.

Schon 2003 aber wurde Server Name Indication (engl. für „Andeutung des Servernamens“) erfunden [RFC 6066: Transport Layer Security (TLS) Extensions: Extension Definitions]. Moderne Browser übermitteln hiermit schon bevor verschlüsselt wird welche Domain sie erwarten. Wenn sich der Browser an diesen Standard hält, dann kann der Webserver auch ohne verschiedene IP-Adressen erkennen welches Zertifikat er nutzen muss.

Funktioniert das auch immer?

Nein! Sowohl der Browser als auch der Server muss das Verfahren unterstützen. Probleme gibt es wenn der Nutzer mit einem Internet Explorer Version 6 oder mit Windows XP unterwegs sind. Beides ist aber inzwischen selten. Mit anderen Browsern und Betriebssystemen gibt es keine Probleme mehr.

Und der Server? Das haben wir Administratoren selbst in der Hand. Ich nutze Apache mit mod_gnutls. Server Name Indication versteht dieses seit irgendwann zwischen April 2005 (Version 0.2.0) und November 2007 (Version 0.3.4).

Also passt alles?

Leider nein. Ich hatte alles nach Anleitung eingerichtet. Die Fehlermeldungen sind nicht verschwunden. Immer wieder beschwerte sich der Browser: das Zertifikat ist falsch.

Suchen wir mit Google. Es gibt fast kein Problem, das ein anderer schon hatte. Tatsächlich: Jan Krüger beschreibt das gleiche Problem in mod_gnutls and StartSSL level 1 certificates: the problem (and solution).

mod_gnutls berücksichtigt nur die im Feld CN (Common Name) des Zertifikates eingetragene Domain. Dort ist aber nur Platz für eine einzelne Domain. Steht ein Zertifikat für mehrere Domains (z.B. mit ohne ohne „www“), so werden diese in einem anderen Feld eingetragen: Subject Alternative Name / dnsName. Solche Zertifikate hatte ich von StartSSL bekommen.

Jan hat hierfür einen Patch geschrieben und veröffentlicht. Allerdings unterstützt seine Lösung nur bis zu vier Domains pro Zertifikat. In den meisten Fällen reicht das sicherlich. Trotzdem wollte ich das Problem noch allgemeiner lösen.

Meine Version des gnu_tls-Patches kann mit einer beliebigen Anzahl von Domains in einem Zertifikat umgehen.

Ich wollte meine Verbesserung auch anderen Nutzern von Debian und mod_gnutls einfach zur Verfügung stellen. Eine E-Mail habe ich an den Debian-Paket-Betreuer und den Entwickler von mod_gnutls geschickt. Beide kamen unzustellbar zurück.

Abweisen unbekannter Anrufer (ACR) im ISDN

posted on

Vor ein paar Tagen habe ich - wie viel zu oft - wieder meinem Bildfernschreiber (neudeutsch einfach kurz Fax genannt) nur Werbung entnommen. Jede dieser Sendungen kostet mich ein paar Eurocent für das Thermopapier und strapaziert darüber hinaus meine Nerven.

Als Gegenmittel habe ich mir neuerdings bei der Telekom das Dienstmerkmal Abweisen unbekannter Anrufer (ACR) beantragt. Ich gehe davon aus, dass quasi alle Werbesendungen mit unterdrückter Rufnummer übermittelt werden, damit die Absender möglichst nicht für Beschwerden erreichbar sind. Im Gegensatz dazu stammen alle meine erwünschten Fernschreiben von Anschlüssen, die ihre Rufnummer ganz normal übermitteln.

Angeboten wird dieses Merkmal von der Telekom kostenlos. Dass dies so ist liegt vermutlich an der EU-Telekommunikations-Datenschutzrichtlinie 97/66/EC, die fordert, dass der Angerufene die Möglichkeit haben muss, ankommende Anrufe, bei denen die Rufnummernanzeige durch den Anrufenden unterdrückt wurde, auf einfache Weise und unentgeltlich abzuweisen. (Zitiert aus einem Dokument der RegTP.) Umgesetzt wurde dieses in der TDSV in § 11, Abs. 1. Dass dieses durch den Angerufenen auf einfache Weise möglich ist, möchte ich jedoch noch bezweifeln. Zum einen kann ACR nicht selbständig aktiviert werden, sondern muss bei der Telekom beauftragt werden und zum anderen ist die Ansage, die ein abgewiesener Anrufer erhält für diesen nicht wirklich hilfreich. (Dieser Anschluss ist aus technischen Gründen vorübergehend nicht erreichbar. Bitte versuchen Sie es später wieder.). Aus den Mobilfunknetzen sind wieder andere Ansagen oder gar einfach ein Besetztzeichen zu hören.

Besser realisiert wurde dieses Dienstmerkmal von der Swisscom (schweizer Telefongesellschaft), dort kann der Kunde ACR durch wählen von *99# selbst aktivieren und mit #99# wieder deaktivieren. Auch die Ansage, die ein Anrufer gegebenenfalls hört, ist für diesen aufschlussreicher: Der Swisscom Kunde wünscht keine Anrufe mit unterdrückter Rufnummer. Es wäre wünschenswert, dass die Telekom sich hieran ein Beispiel nimmt.

Zu diesem Dienstmerkmal möchte ich abschließend noch anmerken, dass nur Anrufe abgewiesen werden, deren Anschluss eine Rufnummer übertragen könnte, aber eine permanente oder fallweise Rufnummernunterdrückung (CLIR) aktiviert wurde. Wird die Nummer aus technischen Gründen nicht übermittelt (beispielsweise Kunde einer analogen Vermittlungsstelle oder Gespräch über einen Netzbetreiber, der Rufnummernübermittlung nicht unterstützt), so wird der Anruf nicht abgewiesen. Sollte ein Anrufer zum Schutz seiner Privatsphäre auf die Rufnummernunterdrückung nicht verzichten können, aber einen wichtigen Anruf zu einer geschützten Rufnummer führen müssen, so kann er dieses Gespräch als handvermitteltes Gespräch bei der Telekom unter der Rufnummer 0180-20-01033 beantragt werden. Unter dieser Rufnummer können übrigens auch R-Gespräche (Gespräche, bei denen der angerufene den Verbindungspreis bezahlt), P-Gespräche (Gespräche mit einer bestimmten natürlichen Person im Ausland) und Notgespräche beantragt werden. Wenn man selbst eine Verbindung nicht erstellen kann, so kann in wichtigen Fällen die Handvermittlung oft noch weiterhelfen.

Nachtrag: Inzwischen habe ich ACR wieder abschalten lassen. Die Telekom hatte mir dieses Dienstmerkmal auf allen MSNs geschaltet. Als ich dies reklamierte, bekam ich ein paar Tage später einen Anruf von einem freundlichen Mitarbeiter der Telekom, der mir erklärte, dass er nun verschiedene Versuche unternahm, dies nicht auf alle MSNs zu schalten, die Konfigurationssoftare diese Einstellung jedoch immer abgelehnt hätte. Somit kann ich dies nun leider nicht nutzen, da ich meinen Telefonanschluss mit meinem Mitbewohner teile, der ACR (verständlicherweise) nicht nutzen möchte.

Nachtrag am 2007-11-04: Die TDSV wurde inzwischen überarbeitet, so dass obige Paragraphenangabe nicht mehr zutreffend ist. Das Merkmal wird von der Telekom jedoch noch immer angeboten, auch wenn es der Hotline nicht immer bekannt ist. Es sollte helfen den Telekom-Mitarbeiter gegebenenfalls auf die eigenen Leistungsbeschreibungen hinzuweisen. Das Dienstmerkmal ACR ist bei der Telekom als Abweisen unbekannter Anrufer in der Leistungsbeschreibung Zusätzliche Leistungen am T-ISDN Mehrgeräteanschluss zu finden. In der Preisliste Zusätzliche Leistungen T-ISDN Mehrgeräteanschluss ist es ebenfalls als unentgeltlich aufgeführt und trägt die Artikelnummer 61149.

Jabber! - Wieso Jabber?

posted on

Wie an anderer Stelle auf meiner Website zu lesen ist, nutze ich als Instant-Messenger-System Jabber. Oft werde ich gefragt, wieso ich nicht wie alle anderen auch ICQ, AIM oder dergleichen nutze. Nun, das kann ich erklären:

ICQ nutze ich nicht, da das Protokoll von vorn bis hinten unsicher ist. Viele wissen wahrscheinlich (oder auch nicht), dass der Authorisierungs-Anforderung bei ICQ nur ein Augenschein ist. Jeder kann jeden beliebigen ICQ-Nutzer zu seiner Contact-List hinzufügen, auch ohne die Zustimmung des anderen vorher einzuholen. Dass es so aussieht, als müsste man dies ist nur eine Sache der Original-ICQ-Software. Mit den meisten Nachbau-Programmen geht es deswegen auch ohne. Ebenso ist es nicht möglich jemanden, der einen in seiner "Contact-List" hat, die Zustimmung dazu wieder zu entziehen.

Ein weiteres ICQ-Problem ist, dass wenn man diesen Dienst unbeschränkt nutzen möchte, für alle anderen ICQ-Nutzer es kein Problem ist herauszufinden, welche IP-Adresse man gerade hat. Zwar lässt sich dies verhindern, indem man nur die Kommunikation über den Server zulässt, dann aber ist z.B. die maximale Nachrichtenlänge beschränkt.

Und wieso nicht den MSN-Messenger? Um diesen Dienst zu nutzen habe ich mir eine Mailadresse bei Hotmail zugelegt. (Die Hotmail-Mailadresse ist gleichzeitig auch die Identität beim MSN-Messenger-Dienst.) Obwohl ich diese Hotmail-Adresse nie jemandem gegeben habe und nie öffentlich genutzt habe, erhalte ich Werbemails (Spam) auf dieser Adresse. - Das muss ich mir nicht freiwillig antun.

Am AIM (AOL Instant Messenger) wiederum stört mich, dass man keine Nachrichten an Nutzer verschicken kann, die gerade nicht online sind. Außerdem ist es wiederum nicht so, dass der andere einen erst sieht, wenn man dies zulässt.

Bleibt der Yahoo!-Messenger noch von den bekannteren Diensten übrigt. Ihn habe ich noch nicht so sehr getestet, da ich eigentlich niemanden kenne, der diesen Dienst ebenso nutzt. Aber wieso sollte ich auch den Yahoo!-Messenger nutzen, wenn niemand meiner Bekannten ihn sonst nutzt. Mir scheint es in diesem Dienst auch nicht möglich zu sein, über einen Online-Status anzuzeigen, ob man gerade beschäftigt, Chat-bereit oder sonstetwas ist.

Aufgrund all dieser Überlegungen habe ich mich dazu entschlossen Jabber zu meinen IM-System zu machen. Jabber berut auf einem vollständig öffentlich dokumentierten Protokoll, das in RFC 3920 ff. unter dem Namen XMPP spezifiziert ist. Es gibt Clients für fast alle Betriebssysteme (incl. Unix, Mac, Palm, Windows, ...) und jeder kann das System selbst erweitern wie er will oder seinen eigenen Server in die weltweite Community einbringen.

Jabber führt alle Kommunikation über einen Server durch, damit bekommt kein anderer Jabber-Nutzer die eigene IP-Adresse mitgeteilt und es ist auch kein Problem über andere Medien wie z.B. das Mobiltelefon Jabber zu nutzen, man braucht jeweils nur einen Jabber-Server, der einen versteht.

Jabber berut auf XML und ist damit beliebig erweiterbar. Authorisierungen können beliebig zurückgenommen werden und Nachrichten auf Wunsch sogar mit GPG oder PGP verschlüsselt werden. Ebenso kann man Nachrichtenregeln definieren damit z.B. alle Nachrichten, die während des Urlaubs ankommen automatisch mit einem Hinweis auf die Abwesenheit beantwortet werden.

Und ein auch nicht uninteressanter Aspekt von Jabber ist, dass es Übergänge in alle möglichen anderen IM- und Chat-Systeme gibt. Somit ist z.B. auch die Kommunikation mit Nutzern aus allen anderen oben genannten Instant-Messenger-Diensten möglich.

Weitere Informationen zu Jabber gibt es auf den folgenden Seiten: amessage, jabber.org.

Und wer nun zu guter Letzt auch einmal Jabber ausprobieren möchte und wissen will, was meine Identität im Jabber ist, dem sei sie verraten: mawis@amessage.info

IMUnified - Protokoll

posted on

IMUnified hat vor etwa zwei Jahren angekündigt, ein Protokoll zu schaffen, das es ermöglichen soll, verschiedene Instant Messaging Systeme mit einem Client zu benutzen. Gründungsmitglieder waren unter anderem MSN, Odigo und Yahoo!.

Inzwischen ist es wieder ruhig geworden, ob IMU jemals ernsthaft eingesetzt wird, wird wage ich fast zu bezweifeln. Aber immerhin kann beispielsweise der Yahoo!-Messenger das Protokoll, man muss es nur mit ein paar Registry-Änderungen unter Windows einschalten. Danach hat man die Möglichkeit, sich zusätzlich zu Yahoo! auch in andere IM Dienste anzumelden.

Dies habe ich zum Anlass genommen, mir IM Unified doch einmal anzuschauen und habe ein paar Sessions mit einem Network-Sniffer protokolliert. Das Protokoll ist an sich sehr einfach aufgebaut und erinnert etwas an Protokolle wie SMTP oder HTTP.

Alle Daten werden über eine TCP/IP-Verbindung ausgetauscht. Der Client konnektiert hierzu auf den Port 11319 des Servers. Über diese Verbindung macht er zunächst ein Login-Handshake und tauscht danach Daten aus. Der Austausch erfolgt in Blöcken.

Diese Blöcke haben dabei eine Zeilenstruktur, jede Zeile wird durch \r\n (carriage return, line feed) abgeschlosssen. Die erste Zeile enthält den Typ des Blockes, er gibt die Art des Befehles an. In der zweiten Zeile steht eine ASCII-Dezimalzahl, die angibt, wie viele Bytes der Block (gerechnet ab der dritten Zeile) enthält. Ab der dritten Zeile stehen Parameter-Zeilen, optional gefolgt von einer leeren Zeile zum Abschluss der Headerzeilen, optional gefolgt von einem Body des Blockes (z.B. in Nachrichten-Blöcken). Der Yahoo!-Messenger scheint die leere Zeile grundsätzlich zu übertragen, auch wenn kein Body benötigt wird, der Odigo-Server scheint die Leerzeile nur zu übermitteln, wenn der Body nicht leer ist.

Blocktypen (also Inhalt der ersten Zeile) habe ich bei der Nutzung von Odigo mit dem Yahoo!-Client dabei bisher folgende erhalten: "HELO" (vor Anmeldung, Versionsabsprache, Absprache über Authorisierungstyp), "LOGN Odigo-Nummer" (Austausch der eigentlichen Logininfo), "STAT status" (Setzen und empfangen eines Anwesenheitsstatus, z.B. STAT ONLINE), "ACK 600" (Bestätigung, keine Ahnung was die 600 bedeutet), "LIST ADD Odigo-Nummer" (Hinzufügen eines Nutzers), "PING" (Keep-Alive-Packets, Intervall bestimmt der Server in seinem HELO-Block), "MESG" (Nachricht), "LIST ACCEPT Odigo-Nummer" (Hinzufügen von sich selbst für einen Nutzer erlauben), "DISC" (Abmelden).

Die Kopfzeilen in einem Block haben immer das Format "Bezeichnung: Inhalt". Eine dabei immer enthaltene Kopfzeile ist die ID-Zeile. Sie identifiziert jeden Block eindeutig, der Server spiegelt die enthaltene ID in einer Reference-Kopfzeile, wenn sich ein Block direkt auf einen Block des Clients bezieht (z.B. bei "ACK 600"-Blöcken). Im Falle es Yahoo!-Messengers werden die IDs anscheinend immer als erste Kopfzeile gesendet und haben als Inhalt eine fortlaufende ASCII-Dezimalzahl ab 1001. Auch übermittelt der Yahoo!-Messenger die ID-Zeile immer als erste Kopfzeile. Dies ist vermutlich nicht notwendig, jedenfalls fügt der Odigo-Server seine ID-Zeile nicht immer als erste Kopfzeile ein.

Der erste vom Client zum Server übertragene Block ist ein "HELO"-Block, neben der ID-Zeile enthält dieser Block noch eine Protocol-Zeile ("Protocol: IMIP/1.0") sowie eine leere Zeile. Der Odigo-Server antwortet mit "Auth-Type: imip-md5", "Capabilities: server-lists", ID-Zeile, "Keep-Alive: 60", "Protocol: IMIP/1.0", "Registration: http://www.odigo.com/user", "Service: odigo.com", "ServiceDisplayName: Odigo", Leerzeile, ASCII-String (bei Odigo eine dezimale 32-Bit-ASCII-Zahl, als Salt für das Passwort). Die Zeilen scheinen recht eindeutig zu sein, die Keep-Alive-Zeile scheint zu steuern wie oft der Client einen PING-Block schickt. Der HELO-Block des Servers besitzt interessanterweise keine Reference-Zeile.

Danach sendet der Client einen "LOGN Odigo-Nummer"-Block. Die enthaltenen Zeilen sind: ID-Zeile, "Client: Yahoo! IMIP Client", "Auth-Type: imip-md5" und eine Leerzeile, danach kommt als Body eine 128-Bit-Zahl hexadezimal mit Kleinbuchstaben in ASCII-Darstellung. Diese Zahl ist der md5-Hash des Strings, der durch direktes aneinanderhängen des Salt-Strings aus dem HELO-Block des Servers und dem Passwort gebildet wird. An der UNIX-Kommandozeile kann dies mit dem m5sum-Befehl nachvollzogen werden. Der Wert für das Salt "1919833824" und das Passwort "Passwort" wird wie folgt berechnet: printf "1919833824Passwort" | md5sum. Der Server antwortet darauf mit einem "LOGN Odigo-Nummer"-Block. Kopfzeilen sind nur ID und Reference enthalten.

Anschließend setzt der Client sich online mit einem "STAT ONLINE"-Block, enthaltene Kopfzeilen: ID-Zeile und Leerzeile. Der Server antwortet mit einem "ACK 600"-Block, enthaltene Zeilen: ID und Reference. Andere Online-Stati sind "STAT BUSY", "STAT AWAY" und "STAT OFFLINE" (invisible). Dem Online-Status kann ein erklärender Text als Body des Blockes hinzugefügt werden.

Der Server informiert den Client über die Anwesenheit der Kontakte ebenfalls mit "STAT Status"-Blöcken. Enthaltene Kopfzeilen sind ID und "From: Odigo-Nummer". Es ist keine Leerzeile und kein Body enthalten. Auch bestätigt der Client den Empfang nicht.

Der Server setzt in seinem HELO-Block ein Intervall mit dem der Client PING-Blöcke sendet. Ein solcher Block enthält zwei Kopfzeilen: ID und eine leere. Der Server antwortet mit dem oben beschriebenen "ACK 600"-Block.

Eine abgehende Nachricht verschickt der Yahoo!-Messenger mit einem "MESG"-Block, der die folgenden Zeilen enthält: ID, "To: Odigo-Nummer", "ACK-Type: errors-only", "From: eigene Odigo-Nummer", Leerzeile gefolgt vom Nachrichtenbody. Vom Server kam keine Bestätigung, dies ist vermutlich über die ACK-Type-Zeile gesteuert.

Eine eingehende Nachricht wird ebenfalls in einem "MESG"-Block übertragen. Der Odigo-Server übermittelt dabei jedoch ein paar mehr Kopfzeilen als oben im "MESG"-Block des Clients. Enthalten sind: "Content-Type: text/plain;charset=utf-8", "From: Odigo-Nummer "Nickname"", ID-Zeile, "Time: yyyy-mm-ddThh:mm:ssZ" (Kleinbuchstaben im Datumsstring stehen für entsprechende Zahlen, Angabe in UTC), "To: eigene Odigo-Nummer", Leerzeile und der Nachricht im Body. Der Client bestätigt diesen Block nicht.

Die Abmeldung leitet der Client mit einem "DISC"-Block ein. Enthalten ist eine ID-Zeile und eine leere Zeile. Der Server bestätigt dies mit einem üblichen "ACK 600"-Block. Danach wird die Verbindung getrennt.

Auf die Kontaktliste wird ein Kontakt mit einem "LIST ADD Odigo-Nummer"-Block hinzugefügt. Enthaltene Kopfzeilen sind dabei: ID, "List: Buddy" (vermutlich Auswahl einer Gruppe), "From: Odigo-Nummer" und eine Leerzeile. Der Server antwortet sofort mit einem "ACK 600"-Block. Dass das Gegenüber die Sichtbarkeit erlaubt hat, erfährt man, indem man die Anwesenheit mit einem "STAT Online-Status"-Block übermittelt bekommt.

Wenn jemand einen selbst auf seine Kontaktliste hinzufügen möchte, so bekommt man einen "LIST ADD"-Block ohne Odigo-Nummer in der ersten Zeile. Enthaltene Kopfzeilen sind: "From: Odigo-Nummer "Nick-Name"", ID, "List: Buddy" (ich hatte den entsprechenden Kontakt in dieser Gruppe stehen), Leerzeile und der mit der Authorisierungsanforderung angegebene Text. Die Authorisierung wird mit einem "LIST ACCEPT Odigo-Nummer "Nick-Name""-Block angenommen. Enthaltene Kopfzeilen darin sind ID, From und eine Leerzeile. Der Server bestätigt dies mit einem "ACK 600"-Block.

Update: Ich vermute inzwischen, dass "List: Buddy" keine Gruppe ist, sondern es sich dabei um die Contact-List an sich handelt und andere Listen evtl. Invisible-List und dergleichen sein könnten. Ich habe hierzu jedoch noch keine weiteren Nachforschungen angestellt. Neu habe ich jedoch inzwischen herausgefunden, wie ein Kontakt von der Contact-List entfernt wird (Block des Typs "LIST REMOVE Odigo-Nummer" mit den Headern ID, "List: Buddy" und "From: Odigo-Nummer"; Bestätigung durch den Server mit einem "ACK 600"-Paket) und wie das Hinzufügen zur Contact-List abgelehnt wird (Block des Typs "LIST REJECT Odigo-Nummer" mit den Headern ID und "From: Odigo-Nummer").

Im LOGN-Block des Servers wird die Contact-List des Users gemeldet. Dies geschieht in der Header-Zeile Buddy, die eine Liste von Nutzern (und deren Nick-Name in Anführungszeichen) durch Kommata getrennt enthält.

Folgende weitere ACK-Statusnummern habe ich neben "ACK 600" bisher erhalten: 800 als ich einen STAT-Block ohne Status gesendet habe, 801 als ich einen STAT-Block mit ungültigem Status gesendet habe, 810 wenn ich beim Login ein falsches Passwort verwende, 811 wenn ich beim Login eine ungültige User-ID nutze oder an eine solche User-ID eine Nachricht schicke (die UserID war nicht numerisch, wie bei Odigo immer de Fall).

Einfache IMIP-Session als Beispiel, Beispiel mit Nachrichtentausch und Subscription, Testimplementierung eines einfachen Java-Odigo-Client auf IMIP-Basis.

Darstellung negativer Dualzahlen: Einer- und Zweierkomplement

posted on

Darstellung von ganzen Zahlen

In einer vorgegebenen Anzahl von Bits (meist 8 Bit, 16 Bit, 32 Bit) kann eine ganze Zahl in verschiedenen Weisen dargestellt werden. Drei davon haben wir davon in der Zentralübung kennengelernt. Es ist aus der Darstellung selbst (und damit dem Inhalt der Speicherzelle, des Registers oder wo auch immer die Zahl gerade steht) nicht ersichtlich welche Darstellung gewählt wurde.
Je nach gewählter Darstellung kann mit der vorgegebenen Anzahl von Bits ein verschiedener Wertebereich dargestellt werden.

Die nachfolgende Tabelle stellt für die kennengelernten Kodierungen dar, welches die größte und welches die kleinste darstellbare Zahl ist, wenn n Stellen (Bits) für die Zahl zur Verfügung stehen.

Darstellung kleinste Zahl größte Zahl
"normal" (vorzeichenlos) 0 2n-1
Einerkomplement -(2n-1-1) 2n-1-1
Zweierkomplement -(2n-1) 2n-1-1

Für gebräuchliche Stellenzahlen ergiben sich folgende Wertebereiche:

Stellenzahl Werteb. vorzeichenlos Werteb. Einerkompl. Werteb. Zweierkompl.
8 Stellen = 8 Bit = 1 Byte 0 ... 255 -127 ... 127 -128 ... 127
16 Stellen = 16 Bit = 1 Word 0 ... 65535 -32767 ... 32767 -32768 ... 32767
32 Stellen = 32 Bit = 1 Long Word 0 ... 4294967295 -214748363 ... 214748363 -214748364 ... 214748363

Vorzeichenlose Darstellung

Jede Stelle hat einen Stellenwert von 2n (n ... Nummer der Stelle von rechts an bei 0 beginnen gezählt).

Beispiel: 001001102 = 0*27 + 0*26 + 1*25 + 0*24 + 0*23 + 1*22 + 1*21 + 0*20 = 3810

Diese Darstellung ist die Darstellung, wie sie in Mathe schon häufiger gelehrt wurde, auch heute erst wieder in der HM1-Vorlesung.

Negative Zahlen: 1. Möglichkeit, das Einerkomplement

Diese Darstellung war wohl für die meisten von uns neu. Wir definieren hier, dass das Bit (die Binärstelle), die am weitesten links steht (das MSB, "Most Significant Bit") das Vorzeichen angibt. Eine Null hier kennzeichnet eine positive Zahl, eine Eins kennzeichnet eine negative Zahl.

Für Zahlen, deren linkestes Bit eine Null ist, ist diese Zahlendarstellung identisch mit der vorzeichenlosen Darstellung von oben. Ist das linkeste Bit dagegen eine Eins, so stellt die gleiche Ziffernfolge eine andere Zahl dar! (Vorzeichenlos wäre es eine (positive) Zahl in der oberen Hälfte des Wertebereichs, als Einerkomplement ist es eine negative Zahl.)

Um die Darstellung einer negativen Zahl im Einerkomplement zu erhalten, muss man sich die Binärdarstellung der dazugehörigen positiven Zahl überlegen und danach auf jeder "1" eine "0" und aus jeder "0" eine "1" machen. (Achtung! Dies geht nur, wenn wir eine vorgegebene Anzahl von Stellen haben, da wir auch führende Nullen der positiven Zahl zu einer "1" wandeln müssen.)

Beispiel (vom Übungsblatt): Um die Darstellung der Zahl -3810 im Einerkomplement zu finden, müssen wir uns erst die Darstellung von +3810 ausdenken. Wenn wir 8 Stellen für die Zahldarstellung wählen erhalten wir die Darstellung 001001102 für +38.
Die Darstellung von -38 im Einerkomplement ergibt sich nun durch Vertauschung von "0" und "1" (sogenannte "invertierung"): -3810 = 110110012.

Achtung! 110110012 stellt als Einerkomplement die Zahl -3810 dar, betrachten wir diese Bitfolge jedoch als vorzeichenlose Zahl, so stellt sie dagegen die Zahl 21710 dar.

Bei dieser Darstellung ergibt sich die Besonderheit, dass sowohl "alle Bits Null" als auch "alle Bits Eins" die Zahl "Null" darstellt. Nur das Vorzeichen ist verschieden, was bei "Null" jedoch ohne Bedeutung ist. Damit würde man (der Computer) wenn er +0 (lauter Nullen) mit -0 (lauter Einsen) vergleicht (uns diesen Fall nicht gesondert behandelt) die beiden (eigentlich identischen Zahlen) als verschieden betrachten. Deswegen wird die Einerkomplementdarstellung nicht wirklich benutzt, sondern man arbeitet in der Praxis mit der Zweierkomplementdarstellung (s.o.), bei der dieses Problem nicht auftritt.

Negative Zahlen: 2. Möglichkeit, das Zweierkomplement

Auch beim Zweierkomplement definiert man, dass das linkeste Bit wie beim Einerkomplement das Vorzeichen angibt. Wieder gilt für den Fall, dass dieses linkeste Bit eine "Null" ist, dass die Zahl identisch ist mit der Zahl der vorzeichenlosen Darstellung bei der gleichen Bitfolge. Ist das am weitesten links stehende Bit eine "0", so ist es also egal, ob wir die Zahl vorzeichenlos, als Einerkomplement oder als Zweierkomplement betrachten, da die Darstellungen identisch sind.
Für negative Zahlen (linkestes Bit eine "1") ist die Zahlendarstellung jedoch weder mit der vorzeichenlosen (hier gibt es ja gar keine negativen Zahlen) noch mit dem Einerkomplement identisch.
Wir erhalten die Zweierkomplementdarstellung von negativen Zahlen dadurch, dass wir zuerst das Einerkomplement bilden, dann jedoch noch binär eine Eins addieren.

Die folgende Tabelle stellt verschiedene Zahlen in den drei obigen Darstellungsvarianten dar (wir nehmen 8 Stellen für die Darstellung an):

Ziffernfolge Vorzeichenlos Einerkomplement Zweierkomplement
001001102 +3810 +3810 +3810
000000002 010 (+)010 010
111111112 25510 (-)010 -110
110110012 +21710 -3810 -3910
110100002 +20810 -4710 -4810
101010102 +17010 -8510 -8610

Der entscheidende Vorteil dieser Zweierkomplementdarstellung ist aber nicht, dass es nur eine mögliche Darstellung von "0" gibt (nämlich lauter Nullen, lauter Einsen stellen nun nichtmehr "-0" sondern "-1" dar), sondern dass der Computer mit den Zahlen rechnen kann als seien es vorzeichenlose positive Zahlen. Zur Veranschaulichung ein Beispiel:

Ziffernfolge vorzeichenlos interpretiert als 2er-Kompl. interpret.
001001102
+ 101010102
-----------
110100002
3810
+ 17010
------
20810
+3810
+ -8610
------
-4810

Man sieht daran, dass bei der Zweierkomplementdarstellung es dem Computer, der eine Summe bildet egal sein kann, dass es sich um eine Zweierkomplementdarstellung handelt. Er führt die gleiche Rechnung wie bei vorzeichenlosen Binärzahlen aus. Es ist wiederum einfach unsere Interpretation, ob wir die Zahl als vorzeichenlos oder als Zweierkomplement betrachten.
Haben wir die beiden Summanden zuvor vorzeichenlos betrachtet, so müssen wir auch die Summe als vorzeichenlos betrachten. Haben wir die beiden Summanden als Zweierkomplement betrachtet, so müssen wir auch die Summe als Zweierkomplement betrachten. Die Berechnung stimmt in beiden Fällen (solange wir den Wertebereich der angegebenen Stellenzahl nicht verlassen).

Carry-In und Carry-Out

Da das Ergebnis bei der Addition nur korrekt ist, wenn wir den Wertebereich nicht verlassen (unabhängig ob wir nun mit vorzeichenlosen Zahlen arbeiten oder nicht), müssen wir möglichst einfach erkennen können, ob ein Überlauf (= Verlassen des Wertebereiches) stattgefunden hat oder nicht.
Bei vorzeichenlosen Zahlen passiert eben dieser Überlauf, d.h. das Verlassen des Wertebereiches, wenn wir beim addieren der am weitesten links stehenden Stelle nochmals einen Übertrag haben. (Begründung: Wir müssten ja eigentlich nochmals eine Eins vor die Ziffernfolge des Ergebnisses schreiben, allerdings war in der fest vorgegebenen Anzahl von Stellen kein Platz mehr für diese Eins.) Dieser übertrag von der höchsten Stelle heraus in eine Stelle außerhalb ver vorgegebenen Stellenzahl heißt "Carry-Out".
Betrachten wir die dargestellten Zahlen jedoch nicht als vorzeichenlose Zahlen, sondern als Zweierkomplement, so haben wir durch Experiment festgestellt, dass ein Carry-Out noch keine Überschreitung des Wertebereiches darstellen muss (z.B. (-1)+(-1) = 111111112 + 111111112 = 111111102 = (-2) verursacht ein Carry-Out, ist jedoch korrekt und innerhalb des Wertebereiches).
Um das Verlassen des Wertebereiches zu erkennen, wenn wir die Zahl als Zweierkomplement betrachten, müssen wir zusätzlich das "Carry-In" definieren. Das Carry-In ist ein ggf. auftretender Übertrag von der zweiten Stelle von links in die am weitesten links stehende Stelle. (Carry-In: "in die linkeste Stelle hinein" / Carry-Out: "aus der linkesten Stelle heraus").
Ohne Beweis aber durch Experiment haben wir nun gesehen, dass der Wertebereich beim Zweierkomplement immer dann verlassen wird, wenn das Carry-In ungleich dem Carry-Out ist.

Nachtrag über den Zusammenhang zwischen Carry-In und -Out und den Prozessorflags des 80x86.

(Keine Gewähr für die Richtigkeit der Angaben.)


Unless otherwise credited all material Creative Commons License by Matthias Wimmer