source: trunk/src/update_domains.sh @ 912

Revision 912, 15.4 KB checked in by benjamin, 7 years ago (diff)

ne plus dépendre de AlternC-admintools dans les commentaires

  • Property svn:executable set to *
Line 
1#!/bin/sh
2#
3# $Id: do_domaines.sh,v 1.31 2005/08/29 19:21:31 anarcat Exp $
4# ----------------------------------------------------------------------
5# AlternC - Web Hosting System
6# Copyright (C) 2002 by the AlternC Development Team.
7# http://alternc.org/
8# ----------------------------------------------------------------------
9# Based on:
10# Valentin Lacambre's web hosting softwares: http://altern.org/
11# ----------------------------------------------------------------------
12# LICENSE
13#
14# This program is free software; you can redistribute it and/or
15# modify it under the terms of the GNU General Public License (GPL)
16# as published by the Free Software Foundation; either version 2
17# of the License, or (at your option) any later version.
18#
19# This program is distributed in the hope that it will be useful,
20# but WITHOUT ANY WARRANTY; without even the implied warranty of
21# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22# GNU General Public License for more details.
23#
24# To read the license please visit http://www.gnu.org/copyleft/gpl.html
25# ----------------------------------------------------------------------
26# Original Author of file: Jerome Moinet for l'Autre Net - 14/12/2000
27# Purpose of file: system level domain management
28# ----------------------------------------------------------------------
29#
30
31PATH=/sbin:/bin:/usr/sbin:/usr/bin
32
33set -e
34
35umask 022
36
37########################################################################
38# Constants & Preliminary checks
39#
40
41CONFIG_FILE="/etc/alternc/local.sh"
42
43DOMAIN_LOG_FILE="/var/log/alternc/update_domains.log"
44DATA_ROOT="/var/alternc"
45
46NAMED_TEMPLATE="/etc/bind/templates/named.template"
47ZONE_TEMPLATE="/etc/bind/templates/zone.template"
48
49ACTION_INSERT=0
50ACTION_UPDATE=1
51ACTION_DELETE=2
52TYPE_LOCAL=0
53TYPE_URL=1
54TYPE_IP=2
55TYPE_WEBMAIL=3
56YES=1
57
58if [ ! -x "/usr/bin/get_account_by_domain" ]; then
59    echo "Your AlternC installation is incorrect ! If you are using pre 0.9.4, "
60    echo "you have to install alternc-admintools: "
61    echo "    apt-get update ; apt-get install alternc-admintools"
62    exit 1
63fi
64
65if [ ! -r "$CONFIG_FILE" ]; then
66    echo "Can't access $CONFIG_FILE."
67    exit 1
68fi
69
70. "$CONFIG_FILE"
71
72if [ -z "$MYSQL_HOST" -o -z "$MYSQL_DATABASE" -o -z "$MYSQL_USER" -o \
73     -z "$MYSQL_PASS" -o -z "$DEFAULT_MX" -o -z "$PUBLIC_IP" ]; then
74    echo "Bad configuration. Please use:"
75    echo "   dpkg-reconfigure alternc"
76    exit 1
77fi
78
79if [ -f "$LOCK_FILE" ]; then
80    echo "`date` $0: last cron unfinished or stale lock file." |
81        tee -a "$DOMAIN_LOG_FILE" >&2
82    exit 1
83fi
84
85NAMED_CONF_FILE="$DATA_ROOT/bind/automatic.conf"
86ZONES_DIR="$DATA_ROOT/bind/zones"
87APACHECONF_DIR="$DATA_ROOT/apacheconf"
88OVERRIDE_PHP_FILE="$APACHECONF_DIR/override_php.conf"
89WEBMAIL_DIR="$DATA_ROOT/bureau/admin/webmail"
90LOCK_FILE="$DATA_ROOT/bureau/cron.lock"
91HTTP_DNS="$DATA_ROOT/dns"
92HTML_HOME="$DATA_ROOT/html"
93
94MYSQL_SELECT="mysql -h${MYSQL_HOST} -u${MYSQL_USER}
95                    -p${MYSQL_PASS} -Bs ${MYSQL_DATABASE}"
96MYSQL_DELETE="mysql -h${MYSQL_HOST} -u${MYSQL_USER}
97                    -p${MYSQL_PASS} ${MYSQL_DATABASE}"
98
99########################################################################
100# Functions
101#
102
103print_domain_letter() {
104    local domain="$1"
105
106    local letter=`echo "$domain" | awk '{z=split($NF, a, ".") ; print substr(a[z-1], 1, 1)}'`
107    if [ -z "$letter" ]; then
108      letter="_"
109    fi
110    echo $letter
111}
112
113print_user_letter() {
114    local user="$1"
115
116    echo "$user" | awk '{print substr($1, 1, 1)}'
117}
118
119add_to_php_override() {
120    local fqdn="$1"
121    local escaped_fqdn=`echo "$fqdn" | sed 's/\([\*|\.]\)/\\\\\1/g'`
122
123    if ! grep -q "^${escaped_fqdn}$" "$CHANGED_PHP_OVERRIDES_TMP_FILE"; then
124        echo "$fqdn" >> "$CHANGED_PHP_OVERRIDES_TMP_FILE"
125    fi
126}
127
128add_to_named_reload() {
129    local domain="$1"
130    local escaped_domain=`echo "$domain" | sed -e 's/\./\\\./g'`
131
132    if [ "domain" = "all" ] || grep -q "^all$" "$RELOAD_ZONES_TMP_FILE"; then
133        echo "all" > "$RELOAD_ZONES_TMP_FILE"
134    else
135        if ! grep -q "^${escaped_domain}$" "$RELOAD_ZONES_TMP_FILE"; then
136            echo "$domain" >> "$RELOAD_ZONES_TMP_FILE"
137        fi
138    fi
139}
140
141# we assume that the serial line contains the "serial string", eg.:
142#                 2005012703      ; serial
143#
144# returns 1 if file isn't readable
145# returns 2 if we can't find the serial number
146# returns 3 if a tempfile can't be created
147increment_serial() {
148    local domain="$1"
149    local zone_file="$ZONES_DIR/$domain"
150    local current_serial
151    local new_serial
152    local date
153    local revision
154    local today
155
156    if [ ! -f "$zone_file" ]; then
157        return 1
158    fi
159
160    # the assumption is here
161    current_serial=`awk '/^..*serial/ {print $1}' < "$zone_file"` || return 2
162    if [ -z "$current_serial" ]; then
163        return 2
164    fi
165
166    date=`echo $current_serial | cut -c1-8`
167    revision=`echo $current_serial | sed s/"${date}0\?"/""/g`
168    today=`date +%Y%m%d`
169    # increment the serial number only if the date hasn't changed
170    if [ "$current_date" = "$today" ] ; then
171        revision=$(($revision + 1))
172    else
173        revision=1
174        date=$today
175    fi
176    new_serial="$date`printf '%.2d' $revision`"
177
178    # replace serial number
179    cp -a -f "$zone_file" "$zone_file.$$"
180    awk -v "NEW_SERIAL=$new_serial" \
181        '{if ($3 == "serial")
182             print "            "NEW_SERIAL "   ; serial"
183          else
184             print $0}' < "$zone_file" > "$zone_file.$$"
185    mv -f "$zone_file.$$" "$zone_file"
186
187    add_to_named_reload "$domain"
188
189    return 0
190}
191
192change_host_ip() {
193    local domain="$1"
194    local zone_file="$ZONES_DIR/$domain"
195    local ip="$2"
196    local host="$3"
197    local pattern
198    local a_line
199
200    if [ -z "$host" ]; then
201        host="@"
202    fi
203    a_line="$host       IN      A       $ip"
204    pattern="^$host[[:space:]]*IN[[:space:]]*A[[:space:]]*.*\$"
205    if [ ! -f "$zone_file" ]; then
206        echo "Should change $host.$domain, but can't find $zone_file."
207        return 1
208    fi
209    if grep -q "$pattern" "$zone_file"; then
210        cp -a -f "$zone_file" "$zone_file.$$"
211        sed "s/$pattern/$a_line/" < "$zone_file" > "$zone_file.$$"
212        mv "$zone_file.$$" "$zone_file"
213    else
214        echo "$a_line" >> "$zone_file"
215    fi
216    add_to_named_reload "$domain"
217}
218
219add_host() {
220    local domain="$1"
221    local host_type="$2"
222    local host="$3"
223    local value="$4"
224    local user="$5"
225    local domain_letter=`print_domain_letter "$domain"`
226    local user_letter=`print_user_letter "$user"`
227    local ip
228    local fqdn
229    local vhost_directory
230       
231    delete_host "$domain" "$host"
232
233    if [ "$host" = "@" ]; then
234        change_host_ip "$domain" "$PUBLIC_IP"
235        fqdn="$domain"
236    else
237        if [ "$host_type" = "$TYPE_IP" ]; then
238            ip="$value"
239        else
240            ip="$PUBLIC_IP"
241        fi
242        change_host_ip "$domain" "$ip" "$host"
243        fqdn="${host}.${domain}"
244    fi
245
246    vhost_directory="${HTTP_DNS}/${domain_letter}/${fqdn}"
247    htaccess_directory="${HTTP_DNS}/redir/${domain_letter}/${fqdn}"
248
249    case "$host_type" in
250      $TYPE_LOCAL)
251        ln -snf "${HTML_HOME}/${user_letter}/${user}${value}" \
252                "$vhost_directory"
253        ;;
254
255      $TYPE_WEBMAIL)
256        ln -snf "${WEBMAIL_DIR}" "$vhost_directory"
257        ;;
258
259      $TYPE_URL)
260        mkdir -p "$htaccess_directory"
261        (echo "RewriteEngine on"
262         echo "RewriteRule (.*) ${value}/\$1 [R,L]"
263        ) > "$htaccess_directory/.htaccess"
264        ln -snf "$htaccess_directory" "$vhost_directory"
265        ;;
266       
267      $TYPE_IP)
268        rm -f "$vhost_directory"
269        rm -rf "$htaccess_directory/.htaccess"
270        ;;
271
272      *)
273        echo "Unknow type code: $type" >> "$DOMAIN_LOG_FILE"
274        ;;
275    esac
276}
277
278delete_host() {
279    local domain="$1"
280    local host="$2"
281    local domain_letter=`print_domain_letter "$domain"`
282    local fqdn
283    local escaped_host
284    local escaped_fqdn
285   
286    if [ "$host" = "@" -o -z "$host" ]; then
287        fqdn="$domain"
288        escaped_host=""
289    else
290        fqdn="$host.$domain"
291        escaped_host=`echo "$host" | sed 's/\([\*|\.]\)/\\\\\1/g'`
292    fi
293
294    if [ -f "$ZONES_DIR/$domain" ] ; then
295        cp -a -f "$ZONES_DIR/$domain" "$ZONES_DIR/$domain.$$"
296        sed -e "/^$escaped_host[[:space:]]*IN[[:space:]]*A[[:space:]]/d" \
297            < "$ZONES_DIR/$domain" > "$ZONES_DIR/$domain.$$"
298        mv "$ZONES_DIR/$domain.$$" "$ZONES_DIR/$domain"
299        increment_serial "$domain"
300        add_to_named_reload "$domain"
301    fi
302
303    rm -f "$APACHECONF_DIR/$domain_letter/$fqdn"
304
305    escaped_fqdn=`echo "$fqdn" | sed 's/\([\*|\.]\)/\\\\\1/g'`
306
307    cp -a -f "$OVERRIDE_PHP_FILE" "$OVERRIDE_PHP_FILE.$$"
308    sed -e "/\/${escaped_fqdn}\$/d" \
309        < "$OVERRIDE_PHP_FILE" > "$OVERRIDE_PHP_FILE.$$"
310    mv "$OVERRIDE_PHP_FILE.$$" "$OVERRIDE_PHP_FILE"
311
312    rm -f "$HTTP_DNS/$domain_letter/$fqdn"
313    rm -rf "$HTTP_DNS/redir/$domain_letter/$fqdn"
314}
315
316
317init_zone() {
318    local domain="$1"
319    local escaped_domain=`echo "$domain" | sed -e 's/\./\\\./g'`
320    local zone_file="$ZONES_DIR/$domain"
321    local serial
322
323    if [ ! -f "$zone_file" ]; then
324        serial=`date +%Y%m%d`00
325        sed -e "s/@@DOMAINE@@/$domain/g;s/@@SERIAL@@/$serial/g" \
326            < "$ZONE_TEMPLATE" > "$zone_file"
327        chgrp bind "$zone_file"
328        chmod 640  "$zone_file"
329    fi
330    if ! grep -q "\"$escaped_domain\"" "$NAMED_CONF_FILE"; then
331        cp -a -f "$NAMED_CONF_FILE" "$NAMED_CONF_FILE".prec
332        sed -e "s/@@DOMAINE@@/$domain/g" \
333                < "$NAMED_TEMPLATE" >> "$NAMED_CONF_FILE"
334        add_to_named_reload "all"
335    fi
336}
337
338remove_zone() {
339    local domain="$1"
340    local escaped_domain=`echo "$domain" | sed -e 's/\./\\\./g'`
341    local zone_file="$ZONES_DIR/$domain"
342
343    if [ -f "$zone_file" ]; then
344        rm -f "$zone_file"
345    fi
346
347    if grep -q "\"$escaped_domain\"" "$NAMED_CONF_FILE"; then
348        cp -a -f "$NAMED_CONF_FILE" "$NAMED_CONF_FILE.prec"
349        cp -a -f "$NAMED_CONF_FILE" "$NAMED_CONF_FILE.$$"
350        # That's for multi-line template
351        #sed -e "/^zone \"$escaped_domain\"/,/^};/d" \
352        # That's for one-line template
353        grep -v "^zone \"$escaped_domain\"" \
354            < "$NAMED_CONF_FILE" > "$NAMED_CONF_FILE.$$"
355        mv -f "$NAMED_CONF_FILE.$$" "$NAMED_CONF_FILE"
356        add_to_named_reload "all"
357    fi
358}
359
360change_mx() {
361    local domain="$1"
362    local mx="$2"
363    local zone_file="$ZONES_DIR/$domain"
364    local pattern="^@*[[:space:]]*IN[[:space:]]*MX[[:space:]]*[[:digit:]]*[[:space:]].*\$"
365    local mx_line="@    IN      MX      5       $mx."
366
367    # aller chercher le numéro de la ligne MX
368    # XXX: comportement inconnu si plusieurs matchs ou MX commenté
369    if grep -q "$pattern" "$zone_file"; then
370        cp -a -f "$zone_file" "$zone_file.$$"
371        sed -e "s/$pattern/$mx_line/" < "$zone_file" > "$zone_file.$$"
372        mv "$zone_file.$$" "$zone_file"
373    else
374        echo "$mx_line" >> "$zone_file"
375    fi
376
377    increment_serial "$domain"
378    add_to_named_reload "$domain"
379}
380
381
382########################################################################
383# Main
384#
385
386# Init
387
388touch "$LOCK_FILE"
389DOMAINS_TMP_FILE=`mktemp -t alternc.update_domains.XXXXXX`
390HOSTS_TMP_FILE=`mktemp -t alternc.update_domains.XXXXXX`
391RELOAD_ZONES_TMP_FILE=`mktemp -t alternc.update_domains.XXXXXX`
392CHANGED_PHP_OVERRIDES_TMP_FILE=`mktemp -t alternc.update_domains.XXXXXX`
393
394cleanup() {
395    rm -f "$LOCK_FILE" "$DOMAINS_TMP_FILE" "$HOSTS_TMP_FILE"
396    rm -f "$RELOAD_ZONES_TMP_FILE" "$CHANGED_PHP_OVERRIDES_TMP_FILE"
397    exit 0
398}
399
400trap cleanup 1 2 15
401
402# Query database
403
404cat << EOF | $MYSQL_SELECT | tail -n '+1' > "$DOMAINS_TMP_FILE"
405SELECT membres.login,
406       domaines_standby.domaine,
407       domaines_standby.mx,
408       domaines_standby.gesdns,
409       domaines_standby.gesmx,
410       domaines_standby.action
411  FROM domaines_standby
412       LEFT JOIN membres membres
413               ON membres.uid = domaines_standby.compte
414 ORDER BY domaines_standby.action
415EOF
416
417cat << EOF | $MYSQL_SELECT | tail -n '+1' > "$HOSTS_TMP_FILE"
418SELECT membres.login,
419       sub_domaines_standby.domaine,
420       if (sub_domaines_standby.sub = '', '@', sub_domaines_standby.sub),
421       if (sub_domaines_standby.valeur = '', 'NULL',
422                                             sub_domaines_standby.valeur),
423       sub_domaines_standby.type,
424       sub_domaines_standby.action
425  FROM sub_domaines_standby
426       LEFT JOIN membres membres
427               ON membres.uid = sub_domaines_standby.compte
428 ORDER BY sub_domaines_standby.action desc
429EOF
430
431# Handle domain updates
432
433if [ "`wc -l < $DOMAINS_TMP_FILE`" -gt 0 ]; then
434    echo `date` >> $DOMAIN_LOG_FILE
435    cat "$DOMAINS_TMP_FILE" >> $DOMAIN_LOG_FILE
436fi
437
438# We need to tweak the IFS as $MYSQL_SELECT use tabs to separate fields
439OLD_IFS="$IFS"
440IFS="   "
441cat "$DOMAINS_TMP_FILE" |
442while read user domain mx are_we_dns are_we_mx action; do
443    IFS="$OLD_IFS" 
444
445    DOMAIN_LETTER=`print_domain_letter "$domain"`
446    USER_LETTER=`print_user_letter "$user"`
447
448    add_to_php_override "$domain"
449    add_to_php_override "www.$domain"
450
451    case "$action" in
452      $ACTION_INSERT)
453        # default symlinks
454        ln -snf "${HTML_HOME}/${USER_LETTER}/$user" \
455                "${HTTP_DNS}/${DOMAIN_LETTER}/$domain"
456        ln -snf "${HTML_HOME}/${USER_LETTER}/$user" \
457                "${HTTP_DNS}/${DOMAIN_LETTER}/www.$domain"
458        ln -snf "${WEBMAIL_DIR}" "${HTTP_DNS}/${DOMAIN_LETTER}/mail.$domain"
459                       
460        if [ "$are_we_dns" = "$YES" ] ; then
461            init_zone "$domain"
462            change_host_ip "$domain" "$PUBLIC_IP"
463            change_host_ip "$domain" "$PUBLIC_IP" www
464            change_host_ip "$domain" "$PUBLIC_IP" mail
465        fi
466        ;;
467
468      $ACTION_UPDATE)
469        if [ "$are_we_dns" = "$YES" ] ; then
470            init_zone "$domain"
471            change_mx "$domain" "$mx"
472        else
473            remove_zone "$domain"
474        fi
475        ;;
476
477      $ACTION_DELETE)
478        remove_zone "$domain"
479
480        # remove symlinks
481        rm -f "${HTTP_DNS}/${DOMAIN_LETTER}/"*".$domain"
482        rm -f "${HTTP_DNS}/${DOMAIN_LETTER}/$domain"
483        rm -rf "${HTTP_DNS}/redir/${DOMAIN_LETTER}/"*".$domain"
484        rm -rf "${HTTP_DNS}/redir/${DOMAIN_LETTER}/$domain"
485        ;;
486
487      *)
488        echo "Unknown action code: $action" >> "$DOMAIN_LOG_FILE"
489        ;;
490    esac
491
492    IFS="       "
493done
494IFS="$OLD_IFS"
495
496# Handle hosts update
497
498if [ "`wc -l < $HOSTS_TMP_FILE`" -gt 0 ] ; then
499    echo `date` >> $DOMAIN_LOG_FILE
500    cat "$HOSTS_TMP_FILE" >> $DOMAIN_LOG_FILE
501fi
502
503OLD_IFS="$IFS"
504IFS="   "
505cat "$HOSTS_TMP_FILE" |
506while read user domain host value type action; do
507    IFS="$OLD_IFS"
508
509    if [ "$host" = "@" ]; then
510        FQDN="$domain"
511    else
512        FQDN="$host.$domain"
513    fi
514    if [ "$type" != "$TYPE_IP" ]; then
515        add_to_php_override "$FQDN"
516    fi
517
518    case "$action" in
519      $ACTION_UPDATE | $ACTION_INSERT)
520        add_host "$domain" "$type" "$host" "$value" "$user"
521        ;;
522
523      $ACTION_DELETE)
524        delete_host "$domain" "$host"
525        ;;
526
527      *)
528        echo "Unknown action code: $action" >> "$DOMAIN_LOG_FILE"
529        ;;
530    esac
531
532    IFS="       "
533done
534IFS="$OLD_IFS"
535
536# Update PHP overrides (basedir protection)
537for domain in `cat "$CHANGED_PHP_OVERRIDES_TMP_FILE"`; do
538    /usr/lib/alternc/basedir_prot.sh "$domain" >> "$DOMAIN_LOG_FILE"
539done
540
541# Reload configuration for named and apache
542
543RELOAD_ZONES=`cat "$RELOAD_ZONES_TMP_FILE"`
544if [ ! -z "$RELOAD_ZONES" ]; then
545    if [ "$RELOAD_ZONES" = "all" ]; then
546        rndc reload
547    else
548        for zone in $RELOAD_ZONES; do
549            rndc reload "$zone"
550        done
551    fi
552    apachectl graceful >> "$DOMAIN_LOG_FILE"
553fi
554
555# Cleanup
556
557echo "DELETE FROM domaines_standby" | $MYSQL_DELETE 
558echo "DELETE FROM sub_domaines_standby" | $MYSQL_DELETE 
559
560cleanup
561
562# vim: et sw=4
Note: See TracBrowser for help on using the repository browser.