Re: Using tcpsvd for a remote shell
Laurent Bercot <[email protected]>
| Newsgroups | gmane.comp.misc.pape.general |
|---|---|
| Message-ID | <[email protected]> |
[ long rant ahead. ] > Hi, > after having managed to get tcpsvd and sslio working on the embedded > system i'm developing on, i'm considering getting rid of some other > apps such as a telnetd (named shelld, unmaintainted code...) Ye beware, for here be dragons. And not your standard cute anime faerie dragon puppy; I'm talking big bad scaly cruel-eyed methane-breathed beasties here. > What do i need to do to use tcpsvd to create a proper telnetd > replacement? With sslio it works except for the sh thinking that i'm > non-interactive even when i give the -i option, and not yet having a > "login" inbetween. > Any hints, what do i need to do for this to work properly? > (Do i need to use a pty? what is the best way to create such?) Oooh yes, you need to use a pty, and the best way to create and use a pty is highly, repeat: highly, system-dependent. I've seriously looked into replacing telnetd/sshd a little while ago, and I gave up because doing it properly and cleanly was too much work. Terminal handling is one of the darkest, dirtiest, evilest sides of Unix. Let's put crypto aside for a moment (you can always plug-in some sslio or such if you want crypto; it's a little more complicated than that, because of some client authentication methods needing a terminal whereas your server-side pty-spawning application hasn't started yet, but let's not get distracted) and concentrate on what it means to have a remote shell. 0. tcpsvd, or ucspi-tcp or inetd or whatever, is just a TCP connection handling mechanism. It gives you two fds: a stdin and a stdout. Note that it doesn't even say anything about stderr; for now, fd 2 might as well be closed. (In practice, fd 2 is probably a pipe leading to some multilog-like process. if you set up things correctly.) The only thing you know is that you got fd 0 to read from your client machine and fd 1 to write to it. 1. You want interactivity. I.e. when you hit Backspace, you want your remote shell to erase the last character you typed. (There's a whole rant to write on the Backspace thing on its own, but I'm not the one writing it.) But your standard TCP connection can't do that. It can only transmit the information: "client typed Backspace". It's up to the client side of the connection (read: telnet client) to encode that information, and up to the server side (read: telnetd server) to decode it and use it. 2. Imagine your client runs in a xterm, and you're remotely compiling a Linux kernel. You've typed "make menuconfig", and now you have a nice lxdialog interface. You grab your mouse - oops, you've redimensioned your xterm. But... hey, it's magic: the menuconfig thing has adapted, it fits into your new xterm size. Nope, it's not magic: the client must encode the "window size changed" information, transmit it to the server, the server must decode it and transmit it to the application. And the application must know the client terminal's capabilities in the first place, else how would it draw its screen ? 3. You type "cat /dev/urandom". Oops, bad idea: it scrolls fast, it's garbling your xterm, and you can't stop it. You frantically type ^C, and it finally works: the cat is killed. What happened ? Your telnet client caught the SIGINT, encoded it, transmitted it to the remote side, and your server-side terminal delivered it to the cat. Nice. 1, 2 and 3 are requirements that 0 cannot meet. They're met by some programming layer named "ptys". There are APIs to do all that and more. That's the good news. The bad news is that the APIs are a. not standard and not portable, and b. a PITA to use. a. There is no standard API to even _allocate_ a pty. Single Unix wants you to open /dev/ptmx. BSD wants you to use openpty(). GNU wants you to use getpt(). IRIX wants you to use _getpty(). The list goes on and on. You need to be root to perform some of those, but not all of those, and it changes with OS versions. (DJB has written a thing called ptyget, but it's half-baked, only server-side, and I haven't quite understood the need for the ptyio binary yet. Maybe Paul Jarc, who's patched ptyget to get it working on Linux, could help you with it. I've looked at the code, and I'll just say that DJB has written - and maintained, cough cough - much better programs than that one.) b. Now the APIs are there to do pseudo-terminals _locally_. You want to encode SIGWINCH, SIGINT and such, and transmit them via your puny serial TCP flow, and have the server do the right thing ? You're on your own, dude. Good luck with protocol design. See ? sshd may be huge and stinky, but it deals with very ugly things that aren't that easy to handle. I might one day get the courage to write a killer terminal allocator application, but the day isn't today, and probably not tomorrow either. If you want to take the plunge, feel free, and lots of kudos and thanks if you make it and come up with something good. Oh, and I haven't even mentioned utmp handling. Now that's another piece of fun; I won't spoil the pleasure. :) -- Ska