summaryrefslogtreecommitdiff
path: root/bin/cryptonomic-dyndns-command
blob: c19106655e90ab696499258f5de095195f9aeb45 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/bin/bash

die() { printf 'Error: %s\n' "$*" >&2; exit 1; }

warn() { printf 'Warning: %s\n' "$*" >&2; }

sql_string()
{
	printf '%s' "'${1//\'/\'\'}'"
}

powerdns_sqlite_add_replace_record()
{
	local sql_record_type="$(sql_string "$2")"
	local sql_ip_address="$(sql_string "$3")"

	zone=${1#*.}
	new_name=${label:+$label.}${1: -64 : 64}

	local sql_new_name="$(sql_string "$new_name")"
	local sql_zone="$(sql_string "$zone")"

	if false
	then
		pdnsutil create-zone "$zone"
		pdnsutil add-record "$zone" "$new_name" "$2" "$3"
		return
	fi

	DBDIR=/etc/powerdns
	DBNAME=powerdns.sqlite3
	DB=$DBDIR/$DBNAME

	test -r $DB    && test -w $DB    || die "Wrong permissions on $DB"
	test -r $DBDIR && test -w $DBDIR || die "Wrong permissions on $DBDIR"

	sqlite3 $DB <<END
${SQL_ECHO:+.echo on}
BEGIN;
	DELETE FROM records WHERE type=$sql_record_type AND name=$sql_new_name;

	INSERT INTO records

		(domain_id,
		name,
		type,
		content,
		ttl,
		prio)

		SELECT
			id,
			$sql_new_name,
			$sql_record_type,
			$sql_ip_address,
			3600,
			0
		FROM domains
		WHERE name=$sql_zone;
COMMIT;
END
	r=$?
	[ $r = 0 ] || return $r

	printf '%s %s\n' "$new_name" "$3"
}

add()
{
        local label=
        if [ $# = 3 ]
        then
                label=$1
                shift
        fi
	local record_type ip="$2"
	case "$ip" in
		*.*.*.*) record_type=A ;;
		*:*) record_type=AAAA ;;
		*) exit 1 ;;
	esac

	powerdns_sqlite_add_replace_record "$domain" "$record_type" "$ip"
}

validate_ssh_server()
{
        e=$(mktemp)
        ssh-keyscan -t "$SSH_CLIENT_KEYTYPE" "$ip_address" | grep -q " $SSH_CLIENT_KEYDATA\$" 2>"$e"
        if [ $? = 0 ]
        then
                rm "$e"
                return 0
        else
                cat "$e" >&2
                rm "$e"
                false
        fi
}

validate_dns_label()
{
	if [ $#1 -gt 64 ]
	then
		warn "ignored DNS label: too long"
		return 1
	fi
	case "$1" in
	-*|*--*|*-)
		warn 'ignored DNS label: invalid use of hyphens'
		return 2
		;;
	*[^-A-Za-z0-9]*)
		warn 'ignored DNS label: invalid character'
		return 3
		;;
	esac
	true
}

main()
{
	validate_ssh_server "$ip_address" || return
	add "$domain" "$ip_address"
	for label in $SSH_ORIGINAL_COMMAND
	do
		validate_dns_label "$label" || continue
		add "$label" "$domain" "$ip_address"
	done
}

PEM_DEST=$HOME/public_rsync

eval "$(samizdat-ssh-uid --copy-pem "$PEM_DEST")"

domain=${SSH_CLIENT_DOMAIN}
ip_address=${SSH_CLIENT%% *}

main "$@"