daniele77 / cli

A library for interactive command line interfaces in modern C++
Boost Software License 1.0
1.18k stars 139 forks source link

Authentication feature #57

Open vrobles-gee opened 4 years ago

vrobles-gee commented 4 years ago

Hi @daniele77.

Do you believe it would be easy to add authentication to the library?. I know the scope of such a feature can be huge (for instance, supporting multiple authentication mechanisms, supporting multiple users, supporting different set of commands based on permissions and so on), but we could start with a simple scope, something easy like storing a local credentials file (like htpasswd).

My main concern is that right now any APP using the telnet server is open to the public, and the only way to restrict access is protecting it with networking workarounds like firewall rules. What do you think?

Thanks,

daniele77 commented 4 years ago

@vrobles-gee your request is sensible: security is an important aspect to consider.

However, authentication would be not enough. To simplify the development I chose to use the telnet protocol, which is intrinsically insecure. Even if I would add some authentication mechanism, the data traffic still goes on the wire not encrypted, so it would remain insecure nonetheless.

The right solution by the security point of view could be to switch to ssh protocol, but I'm afraid it would be a huge development effort, and for the moment it is not planned. Sorry.

Currently, we use the library as a debug mechanism in embedded software: we faced the security problem in this way:

daniele77 commented 4 years ago

Some idea to explore in the future:

In both cases, we should differentiate history on the user base and maybe the set of commands by user profile.

wangxuw commented 4 years ago

@vrobles-gee your request is sensible: security is an important aspect to consider.

However, authentication would be not enough. To simplify the development I chose to use the telnet protocol, which is intrinsically insecure. Even if I would add some authentication mechanism, the data traffic still goes on the wire not encrypted, so it would remain insecure nonetheless.

The right solution by the security point of view could be to switch to ssh protocol, but I'm afraid it would be a huge development effort, and for the moment it is not planned. Sorry.

Currently, we use the library as a debug mechanism in embedded software: we faced the security problem in this way:

  • the cli interface is bound to localhost
  • we ssh into the board
  • we telnet into the cli from localhost

new to this project, and i was wondering is there any improvement to integrate complete to localsession? i might help modify this if there is a clear roadmap.

daniele77 commented 4 years ago

to integrate complete to localsession @EFS86340 , I can't understand this. Do you mean using the class CliLocalSession in the example complete? Or merging someway the two examples simplelocalsession and complete? Or what else? Are you suggesting this can help with the "authentication issue" in some way? I'm interested in your ideas: I hope you can help me understand them.

wangxuw commented 4 years ago

to integrate complete to localsession @EFS86340 , I can't understand this. Do you mean using the class CliLocalSession in the example complete? Or merging someway the two examples simplelocalsession and complete? Or what else? Are you suggesting this can help with the "authentication issue" in some way? I'm interested in your ideas: I hope you can help me understand them.

By integrate complete to localsession, I mean that now the example simplelocalsession doesn't support complete functionality, so how about locally support completion without the help of telnet server (by removing the server)?

Moreover, to prevent someone remotely accessing the telnet, it might help to bind the server to 127.0.0.1(localhost) rather than 0.0.0.0 (default ctor), the CliTelnetServer ctor supports binding an address explictly.https://github.com/daniele77/cli/blob/e649e95f2c9f63ae7d213c05cee5ca4a6feaa81a/examples/complete.cpp#L178

daniele77 commented 4 years ago

By integrate complete to localsession, I mean that now the example simplelocalsession doesn't support complete functionality, so how about locally support completion without the help of telnet server (by removing the server)?

If you don't need the telnet access, you can use CliLocalTerminalSession without CliTelnetServer in your application. In this way, you'll get all the features (e.g., autocompletion, history navigation) but your application will depend on boost asio libraries. On the other hand, if your application creates only an object of class CliFileSession, you don't have the boost dependency but you don't get all the features (eg. autocompletion). Why the dependency onboost asio in class CliLocalTerminalSession? Well, this is subtle: the class needs a thread to manage the keyboard, and the code uses boost::asio::io_context to synchronize its callbacks with the main thread. This is useful when in the same application you need both local and telnet access. I'm currently working to remove the boost dependency from CliLocalTerminalSession, too. But it's hard.

Moreover, to prevent someone remotely accessing the telnet, it might help to bind the server to 127.0.0.1(localhost) rather than 0.0.0.0 (default ctor), the CliTelnetServer ctor supports binding an address explictly.

There is this ctor:

CliTelnetServer(detail::asio::BoostExecutor::ContextType& ios, std::string address, unsigned short port, Cli& _cli, std::size_t _historySize=100 ) 

that you can use explicitly with address="127.0.0.1" if you need to restrict the access. However, I made the decision to bind by default to the "0.0.0.0" address.

wangxuw commented 4 years ago

By integrate complete to localsession, I mean that now the example simplelocalsession doesn't support complete functionality, so how about locally support completion without the help of telnet server (by removing the server)?

If you don't need the telnet access, you can use CliLocalTerminalSession without CliTelnetServer in your application. In this way, you'll get all the features (e.g., autocompletion, history navigation) but your application will depend on boost asio libraries. On the other hand, if your application creates only an object of class CliFileSession, you don't have the boost dependency but you don't get all the features (eg. autocompletion). Why the dependency onboost asio in class CliLocalTerminalSession? Well, this is subtle: the class needs a thread to manage the keyboard, and the code uses boost::asio::io_context to synchronize its callbacks with the main thread. This is useful when in the same application you need both local and telnet access. I'm currently working to remove the boost dependency from CliLocalTerminalSession, too. But it's hard.

Moreover, to prevent someone remotely accessing the telnet, it might help to bind the server to 127.0.0.1(localhost) rather than 0.0.0.0 (default ctor), the CliTelnetServer ctor supports binding an address explictly.

There is this ctor:

CliTelnetServer(detail::asio::BoostExecutor::ContextType& ios, std::string address, unsigned short port, Cli& _cli, std::size_t _historySize=100 ) 

that you can use explicitly with address="127.0.0.1" if you need to restrict the access. However, I made the decision to bind by default to the "0.0.0.0" address.

If I commented the CliTelnetServer in complete.cpp example, the complete won't work :( @daniele77

daniele77 commented 4 years ago

If I commented the CliTelnetServer in complete.cpp example, the complete won't work :(

You need to give some work to boost::asio::io_context to avoid the line ios.run() exit immediately:

#ifdef ENABLE_TELNET_SERVER

CliTelnetServer server(ios, 5000, cli);
// exit action for all the connections
server.ExitAction( [](auto& out) { out << "Terminating this session...\n"; } );

#else // ENABLE_TELNET_SERVER

#if BOOST_VERSION < 106600
boost::asio::io_service::work work(ios);
#else
auto work = boost::asio::make_work_guard(ios);
#endif

#endif // ENABLE_TELNET_SERVER

ios.run();

...