summaryrefslogtreecommitdiff
path: root/bin/cryptonomic-dyndns-command
blob: 3e69f5647076fe9b87fdfc5e716c87b58503bde8 (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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/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=cryptonomic.net
	new_name=${label:+$label.}${1: -64 : 64}

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

	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 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,
			600,
			0
		FROM domains
		WHERE name=$sql_zone;

	INSERT INTO records

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

		SELECT
			id,
			$sql_new_name,
			'SSHFP',
			$sql_sshfp,
			600,
			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")"

[ "$SSH_CLIENT_SSHFP_DATA" ] || die wtf

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

main "$@"