0

I am trying to run a C++ application where I am passing some command line arguments to it as follows:

./startServer -ip 10.78.242.4 tcpip{ldap=no;port=2435}

The application is getting crashed because it is not able to get the correct port. Searching over the web, I found that ";" is treated an end of command character (Semicolon on command line in linux) so everything after that is getting ignored. I also understand the putting it inside the quotes will work fine. However, I do not want to force this restriction of putting the arguments in the quotes on the users. So, I want to know is there a way I can process the ";" character with the argv array?

Krishna Chaurasia
  • 8,924
  • 6
  • 22
  • 35
  • Why do you need a semicolon as separator? Wouldn't it be simpler to use something which has no specific meaning within the command line in linux? – AchimGuetlein Jun 06 '18 at 06:22
  • 1
    masking it as \; isn't an option either? the problem seems to be, that the semicolon is not even passed down to your program, so that you can process it within your argv array. If you'd mask it, then it will be passed, and you can process it. otherwhise the shell will 'eat' it – Tom Mekken Jun 06 '18 at 06:23
  • I can do that too but just wanted to know if we can detect the ";" in the above command. – Krishna Chaurasia Jun 06 '18 at 06:24
  • You can't do this for one application. Maybe you can change it with `stty`, but a single line can contain an arbitrary number of commands to start different processes (which all get different arguments). – midor Jun 06 '18 at 06:25
  • 2
    _"putting it inside the quotes will work fine. However, I do not want to force this restriction"_ Why not, it's a pretty standard and accepted thing to do with complex arguments? – acraig5075 Jun 06 '18 at 06:28
  • From the Tom's comment: "that the semicolon is not even passed down to your program", I understand that the semicolon is not even part of the argv array and hence cannot be processed. Correct me if my understanding is wrong. – Krishna Chaurasia Jun 06 '18 at 06:32

2 Answers2

1

The semicolon separates two commands so your command line is equivalent to

./startServer -ip 10.78.242.4 tcpip{ldap=no
port=2435}

Your application will never know anything about either the semi colon or the second command, these will be completely handled by the shell. You need to escape the colon with a back slash or enclose it in quotes. Other characters which may cause similar issues include: $,\-#`'":*?()&|

Complex strings are much easier to pass either from a file or through stdin.

Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
  • Is there a way to access the second line "port=2435}"? Where are they stored actually? I can't find it in the argv array. – Krishna Chaurasia Jun 06 '18 at 08:42
  • No, the second line is nothing to do with your process, the shell will try and run it as a second command which sets the variable "port" to "2345}", you can't access the variable either as it is only a shell variable and not an environment variable and anyway will only be set after your process has exited. – Alan Birtles Jun 06 '18 at 09:08
  • I get it. I even ran ./startServer -ip 10.78.242.4 'tcpip{ldap=no;port=2435}' ;ls and it ran the "ls" command after my process exited. What if someone run some harmful commands (like rm)? Is there a way to prevent that? – Krishna Chaurasia Jun 06 '18 at 09:18
  • Yes, never, ever, ever, ever, ever, ever, ever, ever, ever pass untrusted input to a command line shell without sanitising it, e.g. https://legalhackers.com/advisories/PHPMailer-Exploit-Remote-Code-Exec-CVE-2016-10033-Vuln.html – Alan Birtles Jun 06 '18 at 09:26
  • But how do I sanitize the argument list here when I don't have access to the command line arguments after the ";"? – Krishna Chaurasia Jun 06 '18 at 10:25
  • You mean I can ignore the remaining arguments as is? – Krishna Chaurasia Jun 06 '18 at 10:29
  • As the implementer of a program you have no control of the arguments you are passed. It is up to the caller to ensure that they have escaped any special characters correctly. As the implementer you can make your caller's life easier by not requiring the use of special characters. – Alan Birtles Jun 06 '18 at 11:48
1

You need to quote not only the ; but in the general case also the { and }:

./startServer -ip 10.78.242.4 'tcpip{ldap=no;port=2435}'

If your users are required to type in that complicated last argument, then they can also be made to quote it.

Kusalananda
  • 14,885
  • 3
  • 41
  • 52