]>
Commit | Line | Data |
---|---|---|
189935b1 | 1 | #!/bin/sh |
2 | # linesync.sh, Copyright (c) 2002 Arjen Wolfs | |
3 | # 20020604, sengaia@undernet.org | |
4 | # 20050417, daniel@undernet.org - modified for u2.10.12 | |
5 | # $Id: linesync.sh,v 1.5 2005/04/17 16:59:49 entrope Exp $ | |
6 | # | |
7 | # The code contained is in this file is licenced under the terms | |
8 | # and conditions as specified in the GNU General Public License. | |
9 | # | |
10 | # linesync.sh - centralized ircd.conf updates. | |
11 | # The purpose of this little shell script is to allow a section of an ircd.conf to be | |
12 | # updated from a central location. Hence it is intended to facilitate the automated | |
13 | # distribution of Kill, Jupe, Quarantine and Uworld lines; or any other .conf lines you | |
14 | # may wish to keep synchronized accross all servers on a network. | |
15 | # | |
16 | # This script will download a file called linesync from a specified web server (see | |
17 | # below for configuration), and calculate an md5sum from it. It will then download | |
18 | # a file called linesync.sum from a configurable number of other web servers and | |
19 | # compare the contents of these files against the checksum calculated. If any of the | |
20 | # downloaded checksums mismatch, the program will abort. This provides security to | |
21 | # the centralized update mechanism - in order for it to be compromised, multiple | |
22 | # web servers would have to compromised. | |
23 | # | |
24 | # If all checksums match, the script inspects the .conf lines contained within the | |
25 | # downloaded file. If any .conf lines are found that are not specifically allowed, | |
26 | # the program will abort. This will prevent malicious/dangerous .conf lines (such as | |
27 | # Operator or Connect lines) from being inserted into ircd.conf. | |
28 | # | |
29 | # If all the checks mentioned above are passed, the script checks ircd.conf for a section | |
30 | # that begins with "# BEGIN LINESYNC", and ends with "# END LINESYNC". The section contained | |
31 | # between these two comments is the section maintained by this program. If these lines are not | |
32 | # found in the ircd.conf, they will be appended to it. | |
33 | # Next, the script will build a new ircd.conf by removing all lines present between the two | |
34 | # commented lines mentioned above, and replace them with the contents of the file downloaded. | |
35 | # | |
36 | # Once this has been completed, ircd.conf is backed up and replaced with the newly built version, | |
37 | # and ircd will be rehashed. | |
38 | # | |
39 | # Configuration: This script requires two parameters - the full path to your ircd.conf, and the | |
40 | # full path to your ircd.pid. It will look for a configuration file called linesync.conf in the | |
41 | # same directory as ircd.conf. See the included sample linesync.conf for information on how to | |
42 | # set it up. Obviously, you will need to have web server(s) to use for the distribution of your | |
43 | # .conf update and checksums. This script requires the presence of wget and md5sum, and various | |
44 | # other programs that should be present by default on any Unix system. | |
45 | # | |
46 | # This program should be run from crontab, i.e something like: | |
47 | # 0 0 * * * /home/irc/bin/linesync.sh /home/irc/lib/ircd.conf /home/irc/lib/ircd.pid | |
48 | # | |
49 | # This program has been tested on and works on FreeBSD, Solaris, and Linux. | |
50 | # md5sum is included in GNU textutils. | |
51 | # | |
52 | # Good Luck! | |
53 | # Arjen Wolfs (sengaia@undernet.org), June 9 2002. | |
54 | # | |
55 | ||
56 | # This checks for the presence of an executable file in $PATH | |
57 | locate_program() { | |
58 | if [ ! -x "`which $1 2>&1`" ]; then | |
59 | echo "You don't seem to have $1. Sorry." | |
60 | exit 1 | |
61 | fi | |
62 | } | |
63 | ||
64 | # This checks for the presence of any file | |
65 | check_file() { | |
66 | if [ ! -f "$1" ]; then | |
67 | echo "There doesn't appear to be a $1. Sorry." | |
68 | exit 1 | |
69 | fi | |
70 | } | |
71 | ||
72 | # Try to find programs we will need | |
73 | locate_program wget && locate_program egrep && locate_program diff | |
74 | ||
75 | # try to find GNU awk | |
76 | awk_cmd=`which gawk` | |
77 | if [ $? -ne 0 ]; then | |
78 | awk_cmd="" | |
79 | fi | |
80 | ||
81 | # try to find an appropriate md5 program | |
82 | # BSD md5 capability courtesy of spale | |
83 | md5_cmd=`which md5sum` | |
84 | if [ -z "$md5_cmd" ]; then | |
85 | md5_cmd=`which md5` | |
86 | if [ -z "$md5_cmd" ]; then | |
87 | echo "No MD5 capable programs found (I looked for md5sum and md5)." | |
88 | exit | |
89 | else | |
90 | md5_cmd="$md5_cmd -q" | |
91 | fi | |
92 | fi | |
93 | ||
94 | if [ -z "$awk_cmd" ]; then | |
95 | locate_program awk | |
96 | is_gawk=`echo | awk --version | head -1 | egrep '^GNU.+$'` | |
97 | if [ -z "$is_gawk" ]; then | |
98 | echo "Your version of awk is not GNU awk. Sorry." | |
99 | exit 1 | |
100 | fi | |
101 | awk_cmd="awk" | |
102 | fi | |
103 | ||
104 | # Check for required command line parameters | |
105 | if [ -z "$1" -o -z "$2" ]; then | |
106 | echo "Usage: $0 <conf_path> <pid_path>" | |
107 | echo " <conf_path> Full path to ircd.conf (/home/irc/lib/ircd.conf)" | |
108 | echo " <pid_path> Full path to ircd.pid (/home/irc/lib/ircd.pid)" | |
109 | exit 1 | |
110 | fi | |
111 | ||
112 | # check and set up stuff | |
113 | diff_cmd="diff" | |
114 | cpath=$1 | |
115 | ppath=$2 | |
116 | check_file $cpath | |
117 | dpath=`dirname $cpath` | |
118 | lpath="$dpath/linesync.conf" | |
119 | check_file $lpath | |
120 | save_dir=$PWD; cd $dpath | |
121 | tpath=$PWD; cd $save_dir | |
122 | tmp_path="$dpath/tmp" | |
123 | mkdir $tmp_path > /dev/null 2>&1 | |
124 | ||
125 | # load and check configuration | |
126 | . $lpath | |
127 | if [ -z "$LINE_SERVER" -o -z "$LINE_CHECK" -o -z "$ALLOWED_LINES" ]; then | |
128 | echo "Please setup $lpath correctly." | |
129 | exit 1 | |
130 | fi | |
131 | ||
132 | # Not all versions of date support %s, work around it | |
133 | TS=`date +%Y%m%d%H%M%S` | |
134 | TMPFILE="$tmp_path/linesync.$TS" | |
135 | LSFILE="$LINE_SERVER""linesync" | |
136 | # Attempt to download our .conf update | |
137 | wget --cache=off --quiet --output-document=$TMPFILE $LSFILE > /dev/null 2>&1 | |
138 | if [ ! -s "$TMPFILE" ]; then | |
139 | echo "Unable to retrieve $LSFILE. Sorry." | |
140 | rm $TMPFILE > /dev/null 2>&1 | |
141 | exit 1 | |
142 | fi | |
143 | ||
144 | # Check whether the file contains any disallowed .conf lines | |
145 | bad_lines=`egrep '^[^'$ALLOWED_LINES'|#]+' $TMPFILE` | |
146 | if [ ! -z "$bad_lines" ]; then | |
147 | echo "The file downloaded in $TMPFILE contains the following disallowed line(s):" | |
148 | echo $bad_lines | |
149 | exit 1 | |
150 | fi | |
151 | ||
152 | # Check whether somebody tried to sneak a second block onto some line | |
153 | bad_lines=`egrep -i '}[ ]*;[ ]*[a-z]+[ ]*{' $TMPFILE` | |
154 | if [ ! -z "$bad_lines" ] ; then | |
155 | echo "The file downloaded in $TMPFILE contains the following multi-block line(s):" | |
156 | echo $bad_lines | |
157 | exit 1 | |
158 | fi | |
159 | ||
160 | # check our ircd.conf | |
161 | ircd_setup=`egrep '^# (BEGIN|END) LINESYNC$' $cpath|wc -l` | |
162 | if [ $ircd_setup != 2 ]; then | |
163 | cp $cpath $cpath.orig | |
164 | echo "Performing initial merge on $cpath, original file saved as $cpath.orig." | |
165 | ||
166 | echo "# Do NOT remove the following line, linesync.sh depends on it!" >> $cpath | |
167 | echo "# BEGIN LINESYNC" >> $cpath | |
168 | echo "# END LINESYNC" >> $cpath | |
169 | echo "# Do not remove the previous line, linesync.sh depends on it!" >> $cpath | |
170 | ||
171 | # Do an initial merge to remove duplicates | |
172 | inpath="$tmp_path/linesync.tmp.$TS" | |
173 | $awk_cmd ' | |
174 | { | |
175 | if (!loaded_template) { | |
176 | command="cat " tempfile; tlines=0; | |
177 | while ((command | getline avar) > 0) { template[tlines]=avar; tlines++ } | |
178 | close(command) | |
179 | loaded_template++ | |
180 | } | |
181 | dup_line=0 | |
182 | for (i=0; i<tlines; i++) { | |
183 | if (tolower($0)==tolower(template[i])) { dup_line++; break } | |
184 | } | |
185 | if (!dup_line) print $0 | |
186 | } ' tempfile=$TMPFILE < $cpath > $inpath | |
187 | else | |
188 | inpath=$cpath | |
189 | fi | |
190 | ||
191 | # Get the checksum | |
192 | CKSUM=`$md5_cmd $TMPFILE|cut -d' ' -f1` | |
193 | ||
194 | check_file="$tmp_path/linesync.sum.$TS" | |
195 | for ck_server in $LINE_CHECK; do | |
196 | sumfile="$ck_server""linesync.sum" | |
197 | wget --cache=off --quiet --output-document=$check_file $sumfile > /dev/null 2>&1 | |
198 | if [ ! -s "$check_file" ]; then | |
199 | echo "Unable to retrieve checksum from $sumfile" | |
200 | exit 1 | |
201 | fi | |
202 | if [ "$CKSUM" != "`cat $check_file`" ]; then | |
203 | echo "Checksum retrieved from $sumfile does not match!" | |
204 | exit 1 | |
205 | fi | |
206 | rm -f $check_file | |
207 | done | |
208 | # It all checks out, proceed... | |
209 | ||
210 | # Replace the marked block in ircd.conf with the new version | |
211 | ||
212 | $awk_cmd ' | |
213 | $0=="# BEGIN LINESYNC" { chop++; print; next } | |
214 | $0=="# END LINESYNC" { | |
215 | command="cat " syncfile | |
216 | while ((command | getline avar) > 0) { print avar } | |
217 | close(command) | |
218 | chop-- | |
219 | } | |
220 | { if (!chop) print $0 } | |
221 | ' syncfile=$TMPFILE < $inpath > $tmp_path/linesync.new.$TS | |
222 | ||
223 | # run a diff between current and new confs to see if we updated anything | |
224 | # no point sending the ircd a -HUP if this is not needed, especially on a | |
225 | # busy network, such as Undernet. | |
226 | diff=`$diff_cmd $cpath $tmp_path/linesync.new.$TS` | |
227 | if [ ! -z "$diff" ]; then | |
228 | # Changes were detected | |
229 | ||
230 | # Back up the current ircd.conf and replace it with the new one | |
231 | cp $cpath $dpath/ircd.conf.bk | |
232 | cp $tmp_path/linesync.new.$TS $cpath | |
233 | ||
234 | # Rehash ircd (without caring wether or not it succeeds) | |
235 | kill -HUP `cat $ppath 2>/dev/null` > /dev/null 2>&1 | |
236 | fi | |
237 | ||
238 | # (Try to) clean up | |
239 | rm -rf $tmp_path > /dev/null 2>&1 | |
240 | ||
241 | # That's it... |