Le Nabaztag, comment ca marche ? Partie 3 : Communiquer avec un lapin

Suite de notre série sur le développement d'un serveur alternatif pour faire fonctionner les Nabaztag.

Jusque là, nous avons vu comment le lapin bootait et comment il s'identifiait sur le serveur.

Voyons à présent comment la lapin communique avec le serveur, et surtout, comment lui parler.

Temps de lecture : 6 minutes

Le Nabaztag, comment ca marche ? Partie 2 : l'authentification et la fin du boot

Nouvel épisode de notre série un nabaztag, comment ça marche. Cette fois-ci, nous allons nous attaquer à l'authentification, l'étape juste après la séquence de boot

A la fin de la première partie, nous avions vu que le lapin tentait de se connecter à un serveur XMPP (par défault xmpp.nabaztag.com). C'est sur ce serveur que se déroule l'étape d'authentification, constituée d'une série d'échanges entre le lapin et le serveur.

Etape 1 :

Le lapin envoie le message suivant au serveur :

LAPIN :
<?xml version='1.0' encoding='UTF-8'?>
<stream:stream to='xmpp.nabaztag.com' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>

Rien de particulier ici, le serveur répond alors :

SERVEUR :
<?xml version='1.0'?>
<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='1549628791' from='xmpp.nabaztag.com' version='1.0' xml:lang='en'>

Etape 2 :

Le serveur envoie alors les méthodes d'authentification disponibles :

SERVEUR :
<stream:features>
<mechanisms xmlns='urn:ietf: params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
</mechanisms>
<register xmlns='http://violet.net/features/violet-register'/>
</stream:features>

Le lapin choisit de s'authentifier en MD5 par défaut :

LAPIN :
<auth xmlns='urn:ietf: params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/>

Etape 3 :

La méthode d'authentification ayant été choisie, le serveur envoie donc un challenge pour que le lapin s'identifie :

SERVEUR :
<challenge xmlns='urn:ietf: params:xml:ns:xmpp-sasl'>
bm9uY2U9IjEzNDc2MTcwNTIiLHFvcD0iYXV0a
CIsY2hhcnNldD11dGYtOCxhbGdvcml0aG09bWQ1LXNlc3M=
</challenge>




Le serveur envoie ici son premier challenge encodé en Base64. Une fois décodée, la chaîne vaut :

nonce="1347617052",qop="auth",charset=utf-8,algorithm=md5-sess

(Les messages en Base64 ont volontairement été scindés en plusieurs partie à des fins de mise en page)

Le lapin doit alors répondre correctement pour continuer la séquence :

LAPIN :
<response xmlns='urn:ietf: params:xml:ns:xmpp-sasl'>
dXNlcm5hbWU9IjAwMTNkMzg0NTM1YSIsbm9uY2U9IjEzNDc2MTcwNTIiLGNub25
jZT0iMTQzMzIxNTY1MzU3Mu+/vSIsbmM9MDAwMDAwMDEscW9wPWF1dGgsZGl
nZXN0LXVyaT0ieG1wcC94bXBwLm5hYmF6dGFnLmNvbSIscmVzcG9uc2U9ZDYyN
GNlZmNlYWYzNjBhMzg3NDRjOWM1MTY1ZDZhYzcsY2hhcnNldD11dGYtOA==
</response>

Une fois encore, le message est encodé en Base64. Décodons-le :

username="0013d384535a",
nonce="1347617052",cnonce="1433215653572&#65533;",
nc=00000001,
qop=auth,digest-uri="xmpp/xmpp.nabaztag.com",
response=d624cefceaf360a38744c9c5165d6ac7,charset=utf-8

Examinons de plus près cette réponse du lapin. Il s'agit d'une authentification en mode DIGEST, où le username est l'adresse MAC du lapin.

Le but initial étant de construire un nouveau serveur pour les nabaztag, nous n'avons que peu à faire de l'authentification. Il suffit juste de faire croire au lapin que la séquence qu'il a envoyée est correcte ;)

Normalement, le serveur renvoie donc une réponse du type :

<challenge xmlns='urn:ietf: params:xml:ns:xmpp-sasl'>
XXXX
</challenge>

Où XXXX est de nouveau une chaîne encodée en base64 de la forme :

rspauth=HASH

(Le hash étant ici la réponse au DIGEST)

Etape 4 :

Le lapin demande alors si son authentification est correcte, de la manière la plus simple possible :

<response xmlns='urn:ietf: params:xml:ns:xmpp-sasl'/>

Il suffit alors au serveur de lui répondre OK :)

<success xmlns='urn:ietf: params:xml:ns:xmpp-sasl'/>

A partir de maintenant, le lapin est considéré comme authentifié auprès du serveur.
Nous n'avions donc pas besoin de calculer le hash pour le DIGEST, le lapin s'attendant juste à recevoir un <success /> pour continuer sa séquence de boot.

Les étapes qui suivent ne font pas partie à proprement parler de l'authentification, mais elles constituent la suite de la séquence d'initialisation du lapin. C'est à la fin de cette séquence que le lapin sera pleinement fonctionnel et attendra de nouvelles commandes.

Examinons tout ceci :

LAPIN :
<?xml version='1.0' encoding='UTF-8'?>
<stream:stream to='sackboylocal.eskuel.net' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>

Le lapin initie donc un nouveau Stream, comme au début de l'authentification.

SERVEUR :
<?xml version='1.0'?>
<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='1331400675' from='xmpp.nabaztag.com' version='1.0' xml:lang='en'>
<stream:features>
<bind xmlns='urn:ietf: params:xml:ns:xmpp-bind'>
<required/>
</bind>
<unbind xmlns='urn:ietf: params:xml:ns:xmpp-bind'/>
<session xmlns='urn:ietf: params:xml:ns:xmpp-session'/>
</stream:features>

Le lapin change alors sa resource XMPP, pour marquer qu'il est en mode boot :

LAPIN :
<iq from="0013d384535a@sackboylocal.eskuel.net/" to="xmpp.nabaztag.com" type='set' id='1'>
<bind xmlns='urn:ietf: params:xml:ns:xmpp-bind'>
<resource>boot</resource>
</bind>
</iq>

Le serveur accuse réception de ce changement :

SERVEUR :
<iq id='1' type='result'>
<bind xmlns='urn:ietf: params:xml:ns:xmpp-bind'>
<jid>0013d384535a@xmpp.nabaztag.com/boot</jid>
</bind>
</iq>

Démarrage de session avec cette nouvelle resource

LAPIN :
<iq from='0013d384535a@xmpp.nabaztag.com/boot' to='xmpp.nabaztag.com' type='set' id='2'>
<session xmlns='urn:ietf: params:xml:ns:xmpp-session'/>
</iq>

SERVEUR :
<iq type='result' to='0013d384535a@xmpp.nabaztag.com/boot' from='xmpp.nabaztag.com' id='2'>
<session xmlns='urn:ietf: params:xml:ns:xmpp-session'/>
</iq>

LAPIN :
<iq from='0013d384535a@xmpp.nabaztag.com/boot' to='net.violet.platform@xmpp.nabaztag.com/sources' type='get' id='3'>
<query xmlns="violet:iq:sources">
<packet xmlns="violet: packet" format="1.0"/>
</query>
</iq>

SERVEUR :
<iq from='net.violet.platform@xmpp.nabaztag.com/sources' to='0013d384535a@xmpp.nabaztag.com/boot' id='3' type='result'>
<query xmlns='violet:iq:sources'>
<packet xmlns='violet: packet' format='1.0' ttl='604800'>
fwQAAAx////+BAAFAA7/CAALAAABAP8=
</packet>
</query>
</iq>

Le serveur nous renvoie ici un paquet contenant l'état du lapin en fin de boot (à savoir les oreilles positionnées à la verticale). Le formatage de ces paquets fera l'objet d'un autre article.

LAPIN :
<iq from="0013d384535a@xmpp.nabaztag.com/boot" to="xmpp.nabaztag.com" type='set' id='4'>
<bind xmlns='urn:ietf: params:xml:ns:xmpp-bind'>
<resource>idle</resource>
</bind>
</iq>

Le lapin change de nouveau de resource pour passer en /idle

SERVEUR :
<iq id='4' type='result'>
<bind xmlns='urn:ietf: params:xml:ns:xmpp-bind'>
<jid>0013d384535a@xmpp.nabaztag.com/idle</jid>
</bind>
</iq>

Le serveur accuse réception. Comme précédemment, le lapin démarre alors une nouvelle session sur cette nouvelle resource

LAPIN :
<iq from='0013d384535a@xmpp.nabaztag.com/idle' to='xmpp.nabaztag.com' type='set' id='5'>
<session xmlns='urn:ietf: params:xml:ns:xmpp-session'/>
</iq>

Le serveur accuse réception :

SERVEUR :
<iq type='result' to='0013d384535a@xmpp.nabaztag.com/idle' from='xmpp.nabaztag.com' id='5'>
<session xmlns='urn:ietf: params:xml:ns:xmpp-session'/>
</iq>

LAPIN :
<presence from='0013d384535a@xmpp.nabaztag.com/idle' id='6'></presence>

SERVEUR :
<presence from='0013d384535a@xmpp.nabaztag.com/idle' id='6'></presence>

Le lapin peut alors libérer la resource /boot, maintenant qu'il a commencé une session en /idle

LAPIN :
<iq from='0013d384535a@xmpp.nabaztag.com/boot' to='xmpp.nabaztag.com' type='set' id='7'>
<unbind xmlns='urn:ietf: params:xml:ns:xmpp-bind'>
<resource>boot</resource>
</unbind>
</iq>

SERVEUR :
<iq id='7' type='result' />

Voilà, à partir de ce point, le lapin a terminé sa séquence de boot et d'authentification. Il est désormais prêt à recevoir des ordres de la part du serveur. Nous verrons dans le prochain article comment sont structurés les ordres envoyés au lapin.

Stay tuned !

Temps de lecture : 7 minutes

Le Nabaztag, comment ca marche ? Partie 1 : le boot

Etant donné que j'ai décidé de remonter un serveur Nabaztag, je partage avec vous mes découvertes sur le fonctionnement d'un Nabaztag au travers d'une série d'articles (que vous pourrez retrouver dans la catégorie Nabaztag)

Aujourd'hui, la première partie, la séquence de boot du Nabaztag.

Le lapin, une fois raccordé au secteur, allume ses 4 diodes en Orange.
Les diodes passent progressivement du orange au vert, en suivant les étapes suivantes :

  • Détection du réseau WiFi
  • Echange de la clé cryptage
  • Obtention d'une adresse IP
  • Connexion aux serveurs

Je ne reviendrais pas sur les 3 premières étapes, le lapin étant autonome sur cette phase de connexion.

La 4ème phase est, elle, plus intéressante.

A ce moment, le lapin tente une connexion HTTP au serveur défini dans sa configuration. La requête est de la forme :

GET /bc.jsp?v=0.0.0.10&m=00:13:d3:84:53:5a&l=00:00:00:00:00:00&p=00:00:00:00:00:00&h=4 HTTP/1.0
User-Agent: MTL
Pragma: no-cache

Le fichier bc.jsp est utilisé pour renvoyer un bootcode au lapin, qu'il puisse définir son état au démarrage. Les différents paramètres passés sont les suivants :

  • v : la version du Nabaztag
  • m : l'adresse MAC du lapin
  • l et p : deux adresse MAC, utilisation non identifée
  • h : paramètre inconnu

Le serveur contacté renvoie donc un bootcode d'une centaine de Ko au lapin, qui poursuit ainsi sa séquence de boot.

Un deuxième appel HTTP est alors réalisé, toujours vers le même serveur :

GET /locate.jsp?sn=0013d384535a&h=4&v=21029 HTTP/1.0
User-Agent: MTL
Pragma: no-cache
Icy-MetaData:1

Par cette requête, la lapin précise sa configuration en demandant les adresses des différents serveurs nécessaires à son fonctionnement (le seul paramètre intéressant ici est sn, l'adresse MAC ou numéro de série du lapin, sans les : )

Le serveur répond alors :

ping tagtag.nabaztag.objects.violet.net
broad broad.violet.net
xmpp_domain xmpp.nabaztag.com

Ici, on en apprend un peu plus sur la manière de fonctionner du lapin.

ping est un serveur web, utilisé lorsque le lapin détecte un tag RFID (les Ztamp:s) ou lors de la reconnaissance vocale
broad est également un serveur web, utilisé pour les chorégraphies, les sons, etc
xmpp_domain est un serveur XMPP (Jabber) utilisé pour contrôler le lapin.

C'est sur ce serveur XMPP que viendra ensuite se connecter le lapin, et tentera ainsi de s'identifier.

Mais cela fera l'objet d'un nouvel article ;)

Temps de lecture : 2 minutes

Nabaztag, démo de mon serveur home made

Comme vous le savez peut-être, les Nabaztag, ces charmantes petites créatures sont depuis peu aussi utiles qu'un presse papier de luxe.

La raison ? Tout simplement parce que Mindscape, la société qui a repris le projet de Violet (le créateur du Nabaztag) est en redressement judiciaire, et a décidé d'arrêter l'exploitation des lapins.

Possédant 2 exemplaires de cette bestiole, je trouve dommage de s'arrêter là. C'est pourquoi j'ai décider de coder from scratch un serveur pour faire marcher mes lapins.

Pour le moment, après de nombreuses nuits passées dessus, j'en suis au commencement, mais au moins mon lapin boot et, énorme progrès, j'arrive à présent à lui communiquer des actions !

Ci dessous deux vidéos (d'une qualité pourrie je vous l'accorde) de mon exploit :)

Le serveur est entièrement fait en PHP, et joue le rôle de serveur XMPP pour les lapins (port 5222) et de console d'admin pour les commander (port 5223)

Je vous expliquerais dans un futur proche le fonctionnement de tout ça :)

/me is very proud :D

Pour ceux qui se demandent ce qu'il y a sur les fenêtres :

La première fenêtre en bas est un pseudo serveur HTTP pour servir les 2 accès de boot du lapin.

La deuxième est le serveur XMPP avec lequel communique le lapin.

La troisième est juste un telnet sur le 5223 pour envoyer la commande ST http://192.168.100.2/nabaztag/71.mp3 qui streame le mp3 situé à l'url donnée.

Temps de lecture : 2 minutes