PageRenderTime 1400ms CodeModel.GetById 1115ms app.highlight 10ms RepoModel.GetById 272ms app.codeStats 0ms

/neatx/doc/design.rst

http://neatx.googlecode.com/
ReStructuredText | 339 lines | 249 code | 90 blank | 0 comment | 0 complexity | 7656018a736f22e815a6225827743510 MD5 | raw file
  1============
  2Neatx design
  3============
  4
  5.. contents:: :depth: 3
  6
  7
  8Overview
  9========
 10
 11There are three major components in Neatx:
 12
 13nxserver-login
 14  Responsible for protocol version negotiation and user login. If user login
 15  was successful, ``nxserver`` takes over.
 16
 17nxserver
 18  Responsible for client/server communication once user is logged in (session
 19  list/start/resume/stop).
 20
 21nxnode
 22  Starts ``nxagent``, monitors its output for state changes and errors.
 23
 24Although not part of Neatx, these components are required for its use:
 25
 26nxagent
 27  A headless version of Xorg's X11 server, patched by NoMachine's NXLibs to add
 28  NX support.
 29
 30nxclient
 31  The remote desktop client which runs on the user's desktop/laptop, similar to
 32  clients for VNC and RDP.
 33
 34
 35Detailed Design
 36===============
 37
 38
 39nxserver-login-wrapper
 40----------------------
 41``nxserver-login-wrapper`` functions as a last-resort handler for log messages.
 42It starts ``nxserver-login`` and redirects stderr to itself. Everything read
 43from ``nxserver-login``'s stderr is sent to syslog.
 44
 45
 46nxserver-login
 47--------------
 48This is set as the login shell for the ``nx`` user.
 49
 50On startup, it sends out a greeting banner (e.g. ``HELLO NXSERVER - Version
 513.0.0 GPL``) followed by the standard NX prompt (``NX> 105`` ).
 52``nxserver-login`` checks that the protocol version requested by the client is
 53supported: the first two significant numbers in the protocol version match
 54those of the server (e.g. ``2.1.8`` matches ``2.1.10``, but ``3.1.0`` does not
 55match ``3.0.0``.).
 56
 57When it receives ``login`` from the client, ``nxserver-login`` prompts for the
 58username and password, and invokes ``nxserver`` via a authentication method
 59specified in the configuration. If authentication fails an appropriate error
 60message is sent to the client, to be displayed to the user.
 61
 62
 63nxserver
 64--------
 65This component takes care of most of the client/server communication.  By the
 66time it is connected to the client, the user has already been authenticated, so
 67it doesn't have to concern itself with login/auth. ``nxserver`` receives the
 68``listsession``, ``startsession``, ``restoresession``, ``attachsession`` and
 69``terminate`` commands, parses the arguments, and handles the request:
 70
 71``listsession``
 72   ``nxserver`` queries the `session database`_ for any sessions matching the
 73   request arguments (e.g. session type, owner, state), and prints out the info
 74   in the session list format.
 75
 76``startsession``
 77   ``nxserver`` takes the parsed arguments, and starts ``nxnode``. It then
 78   connects to ``nxnode`` and tells it to start a session with a generated
 79   unique session id. After doing so, ``nxserver`` polls the `session
 80   database`_ until a session with that id appears and is in the ``running``
 81   state.
 82
 83   If the session does not appear (or does not become ``running``) within a
 84   timeout period, ``nxserver`` reports to ``nxclient`` that the session startup
 85   has failed.
 86
 87   If the session does appear and become ``running``, ``nxserver`` sends the
 88   session info to ``nxclient`` (session id, display number, type, auth cookie,
 89   etc). ``nxserver`` then stores the port number that the session display is
 90   listening on. When the ``nxclient`` acknowledges the info with the ``bye``
 91   command, ``nxserver`` execs ``netcat`` to connect stdin/stdout to the session
 92   display port. After this point, the client is talking directly to the
 93   session, and the session opens up on the user's desktop.
 94
 95``restoresession``
 96   ``nxserver`` queries the `session database`_ for any matching sessions
 97   (similar to ``listsession``, but a session id is a mandatory parameter for
 98   this). If a session is found, it connects to the corresponding ``nxnode``
 99   and tells it to restore the session. Once the session is ready, ``nxserver``
100   continues in exactly the same way as with ``startsession`` (i.e. sending the
101   session info to ``nxclient``, then connecting the client to the session via
102   ``netcat``).
103
104``attachsession``
105   This command is used for session shadowing (i.e. allowing a second person to
106   share an existing session). ``nxserver`` queries the `session database`_ for
107   any matching sessions. If a session is found, ``nxserver`` connects to the
108   corresponding ``nxnode`` instance and asks for the `shadow cookie`_. This
109   cookie is then passed to the session's own ``nxnode`` instance, which in
110   turn connects to the original session and shadows it. Once the session is
111   ready, ``nxserver`` continues in exactly the same way as with
112   ``startsession`` (i.e. sending the session info to ``nxclient``, then
113   connecting the client to the session via ``netcat``).
114
115``terminate``
116   Similar to ``restoresession``, ``nxserver`` queries the `session database`_
117   for any matching sessions. If one is found, it connects to the corresponding
118   ``nxnode`` and tells it to terminate the session.
119
120
121nxnode
122------
123This program is spawned by ``nxserver`` as a daemon. On startup, it listens on
124a per-session Unix socket and handles commands sent by ``nxserver`` via this
125socket. ``nxnode`` contains all code required to start the session (e.g.
126setting environment variables).
127
128Supported commands:
129
130``startsession``
131  Starts ``nxagent`` and watches its output. Must be passed the client's
132  parameters to ``startsession``.
133
134``restoresession``
135  Tells the session state machine to resume the session. Clients can connect
136  again once the session reached the ``waiting`` status.
137
138``attachsession``
139  Starts a new shadow session. The `shadow cookie`_ of the session to be
140  shadowed must be passed.
141
142``terminate``
143  Terminates the session and exits ``nxnode``.
144
145``getshadowcookie``
146  .. _shadow cookie:
147
148  Asks the user for permission to hand out the session cookie. If given, or if
149  shadowed by the same user, the session cookie is returned. This can then be
150  used to shadow the session.
151
152``nxnode`` is written using asynchronous I/O because it must read from
153different file descriptors (client connections, programs, etc.) at the same
154time. Threads can't be used because ``nxnode`` needs to start other processes
155and therefore needs ``fork(2)`` (which isn't compatible with threads in Python
156at least).
157
158Internally ``nxnode`` is more or less a state machine controlled by client
159commands and ``nxagent`` output.
160
161The `session database`_ is updated on every major change (e.g. status change).
162
163On session suspension/termination, ``nxagent`` spawns a watchdog process and
164prints a message containing the watchdog's process ID. It then waits for
165SIGTERM to be sent to that process. ``nxnode`` takes care of this.
166
167The agent pid printed out to the session log may differ from the pid that
168``nxnode`` previously had if the command it used to spawn nxagent forks before
169exec'ing.
170
171If ``nxagent`` is still running when the user application [#userapp]_ exits,
172nxstart sends it SIGTERM to shutdown the session.
173
174
175nxdialog
176--------
177This component is invoked by ``nxagent`` to display a dialog to the user inside
178their NX session. One use is to ask the user whether to disconnect, terminate
179the session or cancel when she tries to close the remote desktop window.
180
181
182RPC protocol
183------------
184``nxserver`` and ``nxnode`` communicate via a Unix socket. The protocol
185consists of NUL-byte separated junks of JSON encoded data and is synchronous.
186
187Example request (sent by ``nxserver``, received by ``nxnode``)::
188
189  {
190    "cmd": "start",
191    "args": {
192      "session": "mysession1",
193      "link": "adsl",
194      "type": "unix-kde",
195      …
196    }
197  }\0
198
199Example response (sent by ``nxnode``)::
200
201  {
202    "success": true,
203    "result": true
204  }\0
205
206Recognized exceptions are transported like this (sent by ``nxnode``)::
207
208  {
209    "success": false,
210    "result": [
211      "SessionParameterError",
212      [
213        "Unencrypted connections not supported"
214      ]
215    ]
216  }\0
217
218All other exceptions are transported like this (sent by ``nxnode``)::
219
220  {
221    "success": false,
222    "result": "Some error message"
223  }\0
224
225
226Logging
227-------
228Neatx uses `Python`_'s standard `logging`__ module. All log messages are sent
229to syslog for processing. Debug output can be enabled via the `configuration
230file`_.
231
232.. __: http://docs.python.org/library/logging.html
233
234
235Configuration file
236------------------
237The configuraturation file is located at ``$sysconfdir/neatx.conf`` (usually
238``/etc/neatx.conf``) and is read using `Python`_'s standard `ConfigParser`__
239module. An example configuration file is included with the source at
240``doc/neatx.conf.example``.
241
242.. __: http://docs.python.org/library/configparser.html
243
244
245Session database
246----------------
247The session database is stored in ``$localstatedir/lib/neatx/sessions/``
248(usually ``/var/lib/neatx/sessions/``). Every session has its own directory,
249named after the session ID.
250
251A session's ID is generated by trying to create a new directory in the session
252database. This guarantees unique session IDs.
253
254Typical contents of a session directory:
255
256``app.log``
257  User application [#userapp]_ output.
258
259``authority``
260  Xauth authority file.
261
262``cache-…``
263  Cache for ``nxagent``.
264
265``C-…``
266  ``nxagent`` data.
267
268``neatx.data``
269  Session data serialized using JSON. This is written by ``nxnode`` and read by
270  ``nxserver``.
271
272``nxnode.sock``
273  Socket listened on by ``nxnode``. ``nxserver`` connects to this socket to
274  execute commands.
275
276
277Session states
278--------------
279
280starting
281  ``nxagent`` is starting.
282
283waiting
284  ``nxagent`` is ready for the client to connect, and is listening on its
285  display port.
286
287running
288  ``nxclient`` is connected to ``nxagent`` and the session is fully setup.
289
290suspending
291  Session suspension is in progress. This happens when the connection to
292  ``nxclient`` drops, or the user explicitly requests it.
293
294suspended
295  Session is fully suspended.
296
297terminating
298  Session termination is in progress.
299
300terminated
301  Session is fully terminated, and all associated processes have exited.
302
303
304Language Choice
305===============
306
307All code should be written in Python_. Exceptions can be made for performance
308critical components, which then should be written in C_. The build system is
309Autoconf_ and Automake_.
310
311
312The ``nx`` User
313===============
314NX, as designed by NoMachine, uses SSH_ to connect to the server. It logs in as
315the ``nx`` user, using a well-known ssh DSA private key that is distributed with
316``nxclient``. The server obtains a username and password from the client, and
317uses them to authenticate as the real user. This allows users without system
318accounts to have guest access to NX.
319
320
321Security Considerations
322=======================
323These are the attack vectors requiring consideration:
324
325- Malicious user without a system account exploits ``nxserver-login`` to run
326  commands as the ``nx`` user
327- Malicious user with a system account gains root access, reads auth cookies
328  from nx session database, and connects to another user's session.
329- Malicious user with a system account exploits ``nxserver`` to connect to
330  another user's session.
331
332
333.. [#userapp] User applications such as KDE, Gnome or custom commands.
334
335.. _Autoconf: http://www.gnu.org/software/autoconf/
336.. _Automake: http://www.gnu.org/software/automake/
337.. _C: http://en.wikipedia.org/wiki/C_(programming_language)
338.. _Python: http://www.python.org/
339.. _SSH: http://www.openssh.com/