- Article pages now have a discussion option at the bottom (moderated/captcha, but no registration needed) - recently upgraded to a newer Dokuwiki version, please report problems

Config files for your script

General

For this task, you don't have to write fat parser routines (unless you want it 100% secure or you want a special file syntax) - you can use Bash's source command. The file to be sourced should be formated in key="value" format, otherwise bash will try to interpret commands:

#!/bin/bash
echo "Reading config...." >&2
source /etc/cool.cfg
echo "Config for the username: $cool_username" >&2
echo "Config for the target host: $cool_host" >&2

So, where do these variables come from? If everything works fine, they are defined in /etc/cool.cfg which is a file that's sourced into the current script or shell. Note that this is not the same as executing this file as a script! The sourced file most likely contains something like:

cool_username="guest"
cool_host="foo.example.com"

These are normal statements understood by Bash, nothing special to do. Of course (and that is a big disadvantage under normal circumstances) the sourced file can contain everything that Bash understands, including evil code!

The source command also is available under the name . (dot). The usage of the dot is identical:

#!/bin/bash
echo "Reading config...." >&2
. /etc/cool.cfg
echo "Config for the username: $cool_username" >&2
echo "Config for the target host: $cool_host" >&2

Per-user configs

There's also a way to provide a system-wide config file in /etc and a custom one in ~/ (user's home) to override some system-wide defaults. The user-specific config will only be used when present, in the following example:

#!/bin/bash
echo "Reading system-wide config...." >&2
. /etc/cool.cfg
if [ -r ~/.coolrc ]; then
  echo "Reading user config...." >&2
  . ~/.coolrc
fi

Secure it

As mentioned earlier, the sourced file can contain everything, it's basically an included Bash script. That raises security issues, like the configuring person is able to "execute" arbitrary code when your script is sourcing its config file. You might want to only allow constructs in the form NAME=VALUE in that file (variable assignment syntax) and maybe comments (though, comments are technically unimportant, of course). Imagine the following "config file", containing some "evil" code:

# cool config file for my even cooler script (eh?)
username=god_only_knows
hostname=www.example.com
password=secret ; echo rm -rf ~/*
parameter=foobar && echo "You've bene pwned!";
# hey look, weird code follows...
echo "I am the skull virus..."
echo rm -fr ~/*
mailto=netadmin@example.com

I guess you don't want these echo-commands (which could be any other commands!) to be executed. One way to be a bit safer is to filter only the constructs you want, write the filtered results to a new file and source the new file. Also, we need to be careful that someome hasn't tacked on something nefarious to the end of one of our name=value parameters, perhaps using ; or && command separators. In these cases, perhaps it is simplest to just ignore the line entirely. Egrep (grep -E) will help us here, it filters by description of how a line should look:

#!/bin/bash
configfile='/etc/cool.cfg'
configfile_secured='/tmp/cool.cfg'

# check if the file contains something we don't want
if egrep -q -v '^#|^[^ ]*=[^;]*' "$configfile"; then
  echo "Config file is unclean, cleaning it..." >&2
  # filter the original to a new file
  egrep '^#|^[^ ]*=[^;&]*'  "$configfile" > "$configfile_secured"
  configfile="$configfile_secured"
fi

# now source it, either the original or the filtered variant
source "$configfile"
To make clear what it does: It checks if the file contains something we don't want, if yes, it filters it and writes the filtered contents to a new file. If done, it changes the name stored in the variable configfile from the original name to the name of the secured file. Then, as usual, it sources the file named by that variable, if it is the original one or the secured one.

This filter only allows NAME=VALUE and comments in the file, though it doesn't prevent all methods of executing code. I will address that later.

Discussion

IƱigo, 2010/09/05 16:55

Please take $() in consideration

  inigo@crono:~/tmp/cfg$ cat test.cfg 
  name=fooo
  address="fooo@fooo.org $(echo $(ls))"

Using the article filter:

  inigo@crono:~/tmp/cfg$ bash cfg.sh 
  username: fooo
  address:  fooo@fooo.org cfg.sh test.cfg

The $(echo $(ls)) (or any other command) may get executed.

The same could be done with `...`

Jan Schampera, 2010/09/13 06:34

Yes, you're absolutely right.

I wonder, before tinkering something else into the code, if it makes sense to take this article offline. The way is nice, simple, effective, but unusable, no matter what you do. It is and stays a workaround to not have to code too much for a config file system.

Reinier Boon, 2011/01/19 16:40

I succesfully used a construction like

  MAIL_TO=`perl -ne '/^\s*MAIL_TO\s*=\s*([\s\w@\d,\._-]+)/ && do {print $1; exit;}' $CONFIG_FILE`

to read the users to mail to from a config file...

It depends a bit on what exactly will be in your config variable, you may have to tweak the regexp.

Amine MECIFI, 2011/11/26 12:03

**Please don't delete this tip. It's a good one!

Security wise, if someone is able to temper with the config file, he will be also able to edit the shell script file in first place.

If you are really concerned by the security, you can do the following:

- once you are satisfied that your config file is complete, do a md5sum and hard code it into the shell script. So the script will check the md5sum of the conf file every time it calls it. - The problem with this, is if you change something in the conf file, you need to issue an new md5sum and place in the shell. - You can be more aggressive (paranoid?) but splitting the config file in 2 or more files, test the md5sum of each of them. Then you also test the md5sum of the whole file and you compare everything. This is just a provision for the case where someone comes up with an altered config file but with the same md5sum (theoretically possible).

Jan Schampera, 2011/11/29 07:54

An attacker who can edit the config isn't necessarily able to edit the script, just think of configs in dot-file in the home directory, or the-like.

You are also right, yes, but a warning is absolutely needed here :-)

Enter your comment
 
howto/conffile.txt · Last modified: 2010/02/23 17:50 (external edit)
GNU Free Documentation License 1.3
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0