/neatx/doc/design.rst

http://neatx.googlecode.com/ · ReStructuredText · 339 lines · 249 code · 90 blank · 0 comment · 0 complexity · 7656018a736f22e815a6225827743510 MD5 · raw file

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