Scripting à distance et conséquences

Distribué par le projet Fr.OpenOffice.org

Révision 1.0 – 18/09/2004

Réalisé avec : OOo 1.1.0	Plate-forme / Os : Toutes

Table des Matières

1 Introduction	3

2 Principe d’utilisation à distance	3

2.1 Architecture et pré-requis	3

2.2 Le serveur	3

2.3 Exécution depuis le Client	4

3 Conséquences	5

3.1 Possibilités de connexion	5

3.2 Sécurité	5

4 Précautions	5

5 Annexe 1 : Une macro pour faire le travail	6

6 Annexe 2 : Client « léger » pour python	7

7 Crédits	8

8 Licence	8

Introduction

Le but de ce How-To est d’illustrer le principe d’automatisation d’OpenOffice.org (« scripting ») à travers un réseau local en donnant l’exemple pour un script python simple. Différentes possibilités sont abordées mais surtout les dangers que représentent cette approche et comment limiter certains risques (tout en étant conscient qu’ils ne sont pas supprimés, loin de là).

Le bridge UNO d’OpenOffice.org permet d’utiliser des langages comme java ou python pour créer des scripts externes utilisant l’API OpenOffice.org. Cette approche très puissante permet d’envisager d’utiliser OpenOffice.org comme un serveur sur lequel viendraient se connecter des scripts clients. C’est d’ailleurs comme cela que ça marche pour l’exécution de tels scripts sur la machine elle-même.

Toute la procédure est issue d’une installation sous linux mais fonctionne tout aussi bien sous windows et bien sûr en environnement mixte. Vous remarquerez donc que les chemins dans ce document sont adaptés à linux. Vous aurez quelques adaptations très mineures à faire pour d’autres OS.

Principe d’utilisation à distance

Nous n’exposons dans cet How-To que les principes de communication. Aucune notion avancée n’est nécessaire, que ce soit au niveau de UNO, python ou OOo. Tout au plus quelques notions de base d’adresse IP ... et encore.

Architecture et pré-requis

Nos tests vont s’effectuer sur un réseau local. Il faut donc deux machines que nous appellerons le Serveur et le Client. Il est possible de faire ces tests sur des machines distantes par Internet. Nous y reviendrons.

Nous supposons que la machine Serveur, celle qui va héberger le serveur OpenOffice.org, a pour adresse IP sur le réseau local 192.168.0.10. Le répertoire d’installation d’OpenOffice.org sur cette machine sera noté <OooServerInstall>, le répertoire de l’utilisateur sera noté <OooServerUser>.

L’adresse IP du client qui va se connecter n’est pas nécessaire. Le répertoire d’installation de la machine cliente sera noté <OooClientInstall>. Enfin, le répertoire des scripts sera noté <ClientScritps>.

Le serveur

Pour utiliser un script externe (Python dans notre cas) se connectant à OpenOffice.org, il faut que celui-ci soit lancé en mode « écoute ».

Voir le Developper’s guide pour plus de renseignements. Chapitre 2.3.3 – Making the office listen – http://api.openoffice.org/docs/DevelopersGuide/FirstSteps/FirstSteps.htm

En effet, la communication passe par un processus de communication de type TCP/IP avec une adresse et un port.

Il y a plusieurs moyens de lancer OpenOffice.org pour qu’il écoute (NB : nous parlons ici du Serveur).

Manuellement - En ligne de commande

Fermer toute instance de OOo (y compris le « Démarrage Rapide » pour ceux qui sont sous windows)

Ouvrir une console et lancer la commande

<OooServerInstall>/program/soffice "-accept=socket,host=192.168.0.10,port=2002;urp;"

Les deux éléments importants sont host= et port=. Nous voyons ici que nous lançons le serveur pour qu’il écoute ce qui arrive sur son interface réseau (c’est à dire, ici, le réseau local sur lequel il est connecté) et que le port d’écoute est 2002.

Une application OpenOffice.org s’ouvre (comme si de rien n’était)

Automatiquement - À chaque démarrage

Il est possible de rajouter un paramétrage dans les fichiers de configuration d’OpenOffice.org pour que la procédure précédente s'exécute à chaque lancement.

Editer le fichier <OooServerUser>/user/registry/data/org/openoffice/Setup.xcu

Rajouter dans la branche <node oor:name="Office"/>

<prop oor:name="ooSetupConnectionURL" oor:type="xs:string">

<value>socket,host=192.168.0.10,port=2002;urp;</value>

</prop>

Ainsi à chaque lancement d’OpenOffice.org, celui-ci sera en mode écoute de tout ce qui arrive au port 2002 de l’adresse 192.168.0.10

A ce stade, le Serveur est prêt à recevoir les ordres du Client ...

Exécution depuis le Client

Nous allons donc depuis notre machine cliente envoyer une série d’ordres au serveur OpenOffice.org. Tout ceci se passe par l’intermédiaire de UNO qui va transmettre les instructions de l’API à l’adresse indiquée.

A titre d’exemple, nous allons utiliser le très connu principe du « Hello World » adapté à pyUNO que nous pouvons trouver à cette adresse :http://udk.openoffice.org/python/python-bridge.html

Nous ne rentrerons pas dans le détail mais le reproduisons ici en l’adaptant à notre contexte

import uno

# get the uno component context from the PyUNO runtime

localContext = uno.getComponentContext()

# create the UnoUrlResolver

# on a single line

resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext )

# connect to the running office

ctx = resolver.resolve( "uno:socket,host=192.168.0.10,port=2002;urp;StarOffice.ComponentContext" )

smgr = ctx.ServiceManager

# get the central desktop object

desktop = smgr.createInstanceWithContext( "com.sun.star.frame.Desktop",ctx)

# access the current writer document

model = desktop.getCurrentComponent()

# access the document's text property

text = model.Text

# create a cursor

cursor = text.createTextCursor()

# insert the text into the document

text.insertString( cursor, "Hello World", 0 )

# Do a nasty thing before exiting the python process. In case the

# last call is a oneway call (e.g. see idl-spec of insertString),

# it must be forced out of the remote-bridge caches before python

# exits the process. Otherwise, the oneway call may or may not reach

# the target object.

# I do this here by calling a cheap synchronous call (getPropertyValue).

ctx.ServiceManager

Copions ces quelques lignes dans un nouveau fichier texte. Enregistrons le fichier comme suit : <ClientScripts>/EssaiRemote.py

En regardant ce script de plus près, nous constatons (ligne mise en évidence) que nous retrouvons les mêmes paramètres de connexion que ceux qui nous ont permis d’ouvrir le serveur en écoute (host=192.168.0.10 et port 2002).

Enfin pour lancer le script sur la machine distante, il suffit d'exécuter

<OooClientInstall>/program/python <ClientScripts>/EssaiRemote.py

Remarquez que OOo est livré avec son propre moteur python et qu'exécuter une autre version que vous pourriez avoir sur votre poste risque de ne pas fonctionner.

Si vous avez réglé un éventuel firewall présent sur votre réseau pour laisser passer ce flux, le serveur devrait montrer un document OOo contenant notre Hello World.

Nous avons donc lancé un script à distance. Tout ça pour ça ...

Notre script était simple, mais toute l’API d’OpenOffice.org est normalement disponible par ce biais.

Conséquences

Possibilités de connexion

Les exemples donnés pour la valeur du host dans la chaîne de connexion prennent souvent localhost qui représente la machine elle-même. Ce mécanisme permet donc de se servir du processus décrit pour envoyer des ordres à la machine elle-même.

Cependant, comme nous l’avons vu, une adresse de classe privée (c'est-à-dire sur un réseau privé) est acceptée pour faire le travail sur un réseau local.

De même une adresse IP réelle est tout aussi valide et la résolution DNS est active.

Sécurité

Si nous prenons un peu de recul, nous pouvons constater qu’il est possible de lancer une écoute d’OpenOffice.org sur l’adresse IP publique et ce de manière silencieuse.

Ainsi, la machine est compromise puisque l’APi d’OOo (très fournie) peut être exploitée à distance pour faire tourner un script extérieur et non contrôlé.

Si l’on associe ceci à ce qui peut être décrit de manière paranoïaque sur l’issue 18860, on constate que tout addon, macro ou script externe peut exploiter cette fonctionnalité.

http://www.openoffice.org/issues/show_bug.cgi?id=18860

En effet , sous couvert d’un addon anodin, pouvant même être utile, le fichier Setup.xcu de l’utilisateur peut être manipulé pour que de manière transparente, OOo écoute sur l’adresse publique et un port bien défini. En raffinant un peu, on peut facilement de l’autre côté connaître cette nouvelle ressource disponible ...

Précautions

Heureusement, pour une utilisation de ceci au sein de votre réseau local, il n’y a pas d'ambiguïté. En effet, même si le serveur est connecté à la fois à Internet et à la fois sur le réseau local (passerelle), OOo répondra aux messages provenant du host qui a ouvert l’écoute. Ainsi, si vous écoutez sur votre réseau local 192.168.0.10, tout message arrivant physiquement sur la machine mais par le biais de votre adresse IP publique sera proprement ignoré.

OUF ??!!!?? Pour ma part je recommanderais la prudence et si vous pouvez faire autrement c’est mieux ...

Une des sources du problème vient du fait que l’autorisation d’ouvrir OOo en écoute est dévolue à l’utilisateur et est donc stockée dans des fichiers sur lesquels il a les droits d’écriture.

Si ceci est pour vous de la paranoïa et que tout ceci vous semble logique, acceptable, alors ce qui suit n’est pas pour vous. Pour les autres, voici de quoi rendre les choses un peu plus difficile lors d’une tentative d’intrusion (pas impossible du tout, faites-leur confiance).

Nous avons vu que l’ouverture automatique de OOo en mode écoute était indiquée dans le fichier Setup.xcu. Ce fichier se trouve à deux endroits. Un dans le répertoire share et un dans chaque répertoire user (issu d’une installation -net)

Sans rentrer dans les détails (le lecteur pourra se référer à l’URL http://util.openoffice.org/common/configuration/oor-document-format.html), un environnement de configuration d’un utilisateur est déterminé par applications de couches successives.

Le schéma

Les valeurs par défaut (le Setup.xcu du repertoire share)

Les valeurs de l’utilisateur (le Setup.xcu du répertoire user de l’utilisateur)

Il existe une option permettant de figer un noeud ou une propriété dans ces fichiers xml afin que l’application des couches suivantes soit ignorée sur cet élément. Il s’agit de oor:finalized="true"

Ainsi, pour éviter que l’utilisateur n’ouvre d’instance de OOo en écoute par « inadvertance », il peut être intéressant de compléter le fichier share/registry/data/org/openoffice/Setup.xcu et de mettre l’option « finalized » sur la propriété ooSetupConnectionURL

<prop oor:name="ooSetupConnectionURL" oor:finalized="true">
<value></value>
</prop>

Cette méthode n’est pas la panacée puisque le lancement d’OOo en ligne de commande (comme nous l’avons vu) n’est pas bloqué et si le fichier Setup.xcu de share est modifié, on retrouve le problème. Cependant avec une installation en -net, le dossier share requiert normalement des droits élevés (voire administrateur/root) ce qui pourrait être plus difficile à obtenir par le vecteur d’infection. Et puis, si il y a intrusion, Ils auront probablement plus « intelligent » à faire que de jouer avec OOo...

Annexe 1 : Une macro pour faire le travail

Cet HowTo contient une macro permettant dans la mesure du possible de paramétrer la propriété ooSetupConnectionURL pour que celle-ci ne soit plus modifiable. Cette macro est destinée aux personnes ne désirant pas éditer les fichiers de configuration

Pour l'exécuter, vous devez disposer des droits d'écriture sur le répertoire share/registry de votre répertoire d’installation OpenOffice.org (celui qui contient également le dossier program)

Attention: cette macro est livrée sans aucune garantie. Je vous conseille fortement de sauvegarder votre fichier Setup.xcu dans le même répertoire sous le nom Setup.xcu.save, au cas où...

Vous devez redémarrer complètement OpenOffice.org pour prendre en compte le paramétrage.

Annexe 2 : Client « léger » pour python

Il n'est pas forcement nécessaire d'avoir une version installée de OOo sur la machine cliente.

Nous donnons à titre expérimental (et provisoire) l’ensemble des fichiers nécessaires pour exécuter la partie client sous Python. C’est un sous-ensemble du répertoire program d’OpenOffice.org.

Cela représente encore 22 Mo au lieu des 147 Mo initiaux, mais il devrait être possible d'alléger encore un peu ...

bridgefac.uno.so

connector.uno.so

corereflection.uno.so

implreg.uno.so

introspection.uno.so

invocadapt.uno.so

invocation.uno.so

libcppuhelper3gcc3.so -> libcppuhelpergcc3.so.3

libcppuhelpergcc3.so -> libcppuhelpergcc3.so.3

libcppuhelpergcc3.so.3 -> libcppuhelpergcc3.so.3.1.0

libcppuhelpergcc3.so.3.1.0

libcppu.so -> libcppu.so.3

libcppu.so.3 -> libcppu.so.3.1.0

libcppu.so.3.1.0

libgcc3_uno.so

libpython.so -> libpython.so.2.2.2

libpython.so.2 -> libpython.so.2.2.2

libpython.so.2.2.2

libpyuno.so

libreg.so.3 -> libreg.so.3.1.0

libreg.so.3.1.0

librmcxt.so -> librmcxt.so.3

librmcxt.so.3 -> librmcxt.so.3.1.0

librmcxt.so.3.1.0

libsalhelper3gcc3.so -> libsalhelpergcc3.so.3

libsalhelpergcc3.so -> libsalhelpergcc3.so.3

libsalhelpergcc3.so.3 -> libsalhelpergcc3.so.3.1.0

libsalhelpergcc3.so.3.1.0

libsal.so -> libsal.so.3

libsal.so.3 -> libsal.so.3.1.0

libsal.so.3.1.0

libstdc++.so -> libstdc++.so.5

libstdc++.so.5

libstlport_gcc.so

libstore.so -> libstore.so.3

libstore.so.3 -> libstore.so.3.1.0

libstore.so.3.1.0

liburp_uno.so

nestedreg.uno.so

Nettoyage

python -> python.sh

python-core -> python-core-2.2.2

python-core-2.2.2

pythonloader.py

pythonloader.unorc

pythonloader.uno.so

python.sh

pyunorc

pyuno.so

regtypeprov.uno.so

remotebridge.uno.so

security.uno.so

servicemgr.uno.so

services.rdb

setup_services.rdb

shlibloader.uno.so

simplereg.uno.so

typeconverter.uno.so

typemgr.uno.so

types.rdb

unohelper.py

uno.py

uno.pyc

uuresolver.uno.so

Crédits

Auteur : Laurent Godard – dev.godard@wanadoo.fr

Remerciements : Clément Cordaro, Tony Galmiche, Christophe Thibierge, Alex Thurgood

Intégré par : Sophie Gautier

Dernière modification : 08/09/2004

Contacts : Projet Documentation OpenOffice.org - Fr.OpenOffice.org

Traduction : Alex Thurgood sous le titre « Remote Scripting and Consequences Thereof »

Licence

Appendix

Public Documentation License Notice

The contents of this Documentation are subject to the Public Documentation License Version 1.0 (the "License"); you may only use this Documentation if you comply with the terms of this License. A copy of the License is available at http://www.openoffice.org/licenses/PDL.html.

The Original Documentation is “Scripting à distance et conséquences”. The Initial Writer of the Original Documentation is Laurent Godard Copyright (C) 2004. All Rights Reserved. (Initial Writer contact(s):dev.godard@wanadoo.fr.

Contributor(s): ______________________________________.

Portions created by ______ are Copyright (C)_________[Insert year(s)]. All Rights Reserved. (Contributor contact(s):________________[Insert hyperlink/alias]).

NOTE: The text of this Appendix may differ slightly from the text of the notices in the files of the Original Documentation. You should use the text of this Appendix rather than the text found in the Original Documentation for Your Modifications.

OpenOffice.org Documentation Project How-To

Fr.OpenOffice.org	7 / 8

2004-09-02T10:56:38