summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cady <d@jerkface.net>2020-05-29 07:20:52 -0400
committerAndrew Cady <d@jerkface.net>2020-05-29 07:24:27 -0400
commit0d70aefb72bcef186cd73cb506be8197f740977d (patch)
tree38ee88381450e88d5073568481affb2c09e4ad36
initial commit
-rw-r--r--.gitignore1
-rw-r--r--Makefile27
-rwxr-xr-xcontrol.sh9
-rw-r--r--depends.control2
-rwxr-xr-xdyndns-command.sh92
-rwxr-xr-xpowerdns/add-zone42
-rwxr-xr-xpowerdns/dyndns-command.sh92
-rwxr-xr-xpowerdns/fixperms.sh5
-rw-r--r--powerdns/named.conf10
-rw-r--r--powerdns/pdns.conf17
-rw-r--r--powerdns/pdns.d/bind.conf2
-rw-r--r--powerdns/pdns.d/pdns.local.conf3
-rw-r--r--powerdns/pdns.d/pdns.local.gsqlite3.conf8
-rw-r--r--powerdns/powerdns.sqlite30
-rwxr-xr-xsamizdat-ssh-command324
-rwxr-xr-xsamizdat-ssh-uid39
-rw-r--r--sources.list.d/pdns.list1
17 files changed, 674 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4db28ac
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
control
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..29b9577
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,27 @@
1control: control.sh depends.control .git/refs/heads/master
2 ./control.sh depends.control > $@
3
4DD_USER = dyndns
5DD_GROUP = dyndns
6
7install-dyndns-server:
8ifneq ($(shell id -u),0)
9 $(SUDO_MAKE) $@
10else
11 : apt install pdns
12 : adduser $(DD_USER)
13 chown root:$(DD_GROUP) /etc/powerdns
14 chown pdns:$(DD_GROUP) /etc/powerdns/powerdns.sqlite3
15 chmod g+rwx /etc/powerdns
16 chmod g+rw /etc/powerdns/powerdns.sqlite3
17 $(MAKE) ~$(DD_USER)/.ssh/authorized_keys
18 install src/samizdat-ssh-command /usr/local/bin/
19 install src/dyndns-command.sh ~$(DD_USER)/samizdat-default-command
20endif
21
22define dyndns_authorized_keys_contents
23command="/usr/local/bin/samizdat-ssh-command /etc/powerdns/dyndns-command.sh",no-port-forwarding * Samizdat - YES WE CAN
24endef
25
26~$(DD_USER)/.ssh/authorized_keys:
27 : writing file $@ $(file >$@,$(dyndns_authorized_keys_contents))
diff --git a/control.sh b/control.sh
new file mode 100755
index 0000000..5943455
--- /dev/null
+++ b/control.sh
@@ -0,0 +1,9 @@
1#!/bin/sh
2cat - "$@" <<END
3Package: $(basename $(pwd))
4Source: $(basename $(pwd))
5Version: $(TZ=UTC date -Is | tr -d :- | tr T . | sed 's/+.*//')
6Architecture: $(dpkg-architecture -q DEB_BUILD_ARCH)
7Origin: local
8Maintainer: root <root@localhost>
9END
diff --git a/depends.control b/depends.control
new file mode 100644
index 0000000..710c001
--- /dev/null
+++ b/depends.control
@@ -0,0 +1,2 @@
1Depends: pdns-backend-sqlite3,
2 pdns-server
diff --git a/dyndns-command.sh b/dyndns-command.sh
new file mode 100755
index 0000000..375d50b
--- /dev/null
+++ b/dyndns-command.sh
@@ -0,0 +1,92 @@
1#!/bin/bash
2
3die() { printf '%s\n' "$*" >&2; exit 1; }
4
5sql_string()
6{
7 printf '%s' "'${1//\'/\'\'}'"
8}
9
10powerdns_sqlite_add_replace_record()
11{
12 local sql_new_domain="$(sql_string "$1.$3")"
13 local sql_ip_address="$(sql_string "$2")"
14 local sql_domain="$(sql_string "$3")"
15 local record_type="$(sql_string "$4")"
16
17 DBDIR=/etc/powerdns
18 DBNAME=powerdns.sqlite3
19 DB=$DBDIR/$DBNAME
20
21 test -r $DB && test -w $DB || die "Wrong permissions on $DB"
22 test -r $DBDIR && test -w $DBDIR || die "Wrong permissions on $DBDIR"
23
24 sqlite3 $DB <<END
25${SQL_ECHO:+.echo on}
26BEGIN;
27 DELETE FROM records WHERE type=$record_type AND name=$sql_new_domain;
28
29 INSERT INTO records
30
31 (domain_id,
32 name,
33 type,
34 content,
35 ttl,
36 prio)
37
38 SELECT
39 id,
40 $sql_new_domain,
41 $record_type,
42 $sql_ip_address,
43 3600,
44 0
45 FROM domains
46 WHERE name=$sql_domain;
47COMMIT;
48END
49}
50
51add()
52{
53 local record_type
54 case "$2" in
55 *.*.*.*) record_type=A ;;
56 *:*) record_type=AAAA ;;
57 *) exit 1 ;;
58 esac
59
60 powerdns_sqlite_add_replace_record "$1" "$2" "$domain" "$record_type" \
61 && printf '%s %s\n' "$1.$domain $2"
62}
63
64main()
65{
66 add "$subdomain" "$ip_address"
67
68 set -- $SSH_ORIGINAL_COMMAND
69 while [ $# -ge 2 ]; do
70 d=$1
71 ip=$2
72 shift 2
73
74 case "$d" in
75 *.*) continue;;
76 esac
77
78 add "$d.$subdomain" "$ip"
79 done
80}
81
82PEM_DEST=$HOME/public_rsync
83
84PATH=$HOME/bin:$PATH
85
86eval "$(samizdat-ssh-uid --copy-pem "$PEM_DEST")"
87
88domain=${SSH_CLIENT_DOMAIN}
89subdomain=${SSH_CLIENT_FINGERPRINT}
90ip_address=${SSH_CLIENT%% *}
91
92main "$@"
diff --git a/powerdns/add-zone b/powerdns/add-zone
new file mode 100755
index 0000000..d7f6a13
--- /dev/null
+++ b/powerdns/add-zone
@@ -0,0 +1,42 @@
1#!/bin/sh
2
3usage() { echo "Usage: $0 <database.sqlite3> <domain>" >&2; exit ${1:-1}; }
4
5check_args()
6{
7 [ $# = 2 ] || usage 1
8 database=$1
9 domain=$2
10
11 [ -f "$database" ] || exit 1
12 [ -r "$database" ] || exit 2
13
14 case "$domain" in
15 -h|--help) exec 2>&1; usage 0 ;;
16 *\'*) usage 1 ;;
17 '') usage 1 ;;
18 *.) usage 1 ;;
19 *.*) ;;
20 *) [ "$ALLOW_TLD_ZONE" ] || usage 1 ;;
21 esac
22}
23
24add_zone()
25{
26 local database="$1" domain="$2" soa
27 soa="$domain hostmaster.$domain 1 10800 3600 604800 3600"
28 sqlite3 "$database" <<END
29 begin;
30 delete from domains where name='$domain' and type='NATIVE';
31 insert into domains (name, type) values ('$domain', 'NATIVE');
32
33 insert into records (domain_id, name, content, type, ttl, prio)
34 select id, '$domain', '$soa', 'SOA', 600, 1
35 from domains where name='$domain';
36 commit;
37END
38}
39
40check_args "$@"
41
42add_zone "$@"
diff --git a/powerdns/dyndns-command.sh b/powerdns/dyndns-command.sh
new file mode 100755
index 0000000..375d50b
--- /dev/null
+++ b/powerdns/dyndns-command.sh
@@ -0,0 +1,92 @@
1#!/bin/bash
2
3die() { printf '%s\n' "$*" >&2; exit 1; }
4
5sql_string()
6{
7 printf '%s' "'${1//\'/\'\'}'"
8}
9
10powerdns_sqlite_add_replace_record()
11{
12 local sql_new_domain="$(sql_string "$1.$3")"
13 local sql_ip_address="$(sql_string "$2")"
14 local sql_domain="$(sql_string "$3")"
15 local record_type="$(sql_string "$4")"
16
17 DBDIR=/etc/powerdns
18 DBNAME=powerdns.sqlite3
19 DB=$DBDIR/$DBNAME
20
21 test -r $DB && test -w $DB || die "Wrong permissions on $DB"
22 test -r $DBDIR && test -w $DBDIR || die "Wrong permissions on $DBDIR"
23
24 sqlite3 $DB <<END
25${SQL_ECHO:+.echo on}
26BEGIN;
27 DELETE FROM records WHERE type=$record_type AND name=$sql_new_domain;
28
29 INSERT INTO records
30
31 (domain_id,
32 name,
33 type,
34 content,
35 ttl,
36 prio)
37
38 SELECT
39 id,
40 $sql_new_domain,
41 $record_type,
42 $sql_ip_address,
43 3600,
44 0
45 FROM domains
46 WHERE name=$sql_domain;
47COMMIT;
48END
49}
50
51add()
52{
53 local record_type
54 case "$2" in
55 *.*.*.*) record_type=A ;;
56 *:*) record_type=AAAA ;;
57 *) exit 1 ;;
58 esac
59
60 powerdns_sqlite_add_replace_record "$1" "$2" "$domain" "$record_type" \
61 && printf '%s %s\n' "$1.$domain $2"
62}
63
64main()
65{
66 add "$subdomain" "$ip_address"
67
68 set -- $SSH_ORIGINAL_COMMAND
69 while [ $# -ge 2 ]; do
70 d=$1
71 ip=$2
72 shift 2
73
74 case "$d" in
75 *.*) continue;;
76 esac
77
78 add "$d.$subdomain" "$ip"
79 done
80}
81
82PEM_DEST=$HOME/public_rsync
83
84PATH=$HOME/bin:$PATH
85
86eval "$(samizdat-ssh-uid --copy-pem "$PEM_DEST")"
87
88domain=${SSH_CLIENT_DOMAIN}
89subdomain=${SSH_CLIENT_FINGERPRINT}
90ip_address=${SSH_CLIENT%% *}
91
92main "$@"
diff --git a/powerdns/fixperms.sh b/powerdns/fixperms.sh
new file mode 100755
index 0000000..4879313
--- /dev/null
+++ b/powerdns/fixperms.sh
@@ -0,0 +1,5 @@
1#!/bin/sh
2set -ex
3set -- /etc/powerdns /etc/powerdns/powerdns.sqlite3*
4chown pdns.dyndns "$@"
5chmod ug+rw "$@"
diff --git a/powerdns/named.conf b/powerdns/named.conf
new file mode 100644
index 0000000..7b8f760
--- /dev/null
+++ b/powerdns/named.conf
@@ -0,0 +1,10 @@
1# Debian default: supermaster created zones are written here:
2include "/var/lib/powerdns/supermaster.conf";
3
4# Example for a manually configured slave zone:
5#
6# zone "example.net" {
7# file "/var/lib/powerdns/zones.slave.d/example.net.zone";
8# type slave;
9# masters { 192.0.2.53; };
10# };
diff --git a/powerdns/pdns.conf b/powerdns/pdns.conf
new file mode 100644
index 0000000..50ffa39
--- /dev/null
+++ b/powerdns/pdns.conf
@@ -0,0 +1,17 @@
1# config-dir=/etc/powerdns
2# include-dir=/etc/powerdns/pdns.d
3
4local-address=0.0.0.0
5setgid=pdns
6setuid=pdns
7
8launch=tinydns
9tinydns-dbfile=/etc/powerdns/tinydns.cdb
10
11launch+=gsqlite3
12gsqlite3-database=/etc/powerdns/powerdns.sqlite3
13gsqlite3-dnssec=yes
14
15master
16daemon=yes
17guardian=yes
diff --git a/powerdns/pdns.d/bind.conf b/powerdns/pdns.d/bind.conf
new file mode 100644
index 0000000..01775c1
--- /dev/null
+++ b/powerdns/pdns.d/bind.conf
@@ -0,0 +1,2 @@
1launch+=bind
2bind-config=/etc/powerdns/named.conf
diff --git a/powerdns/pdns.d/pdns.local.conf b/powerdns/pdns.d/pdns.local.conf
new file mode 100644
index 0000000..3616b88
--- /dev/null
+++ b/powerdns/pdns.d/pdns.local.conf
@@ -0,0 +1,3 @@
1# Here come the local changes the user made, like configuration of
2# the several backends that exist.
3
diff --git a/powerdns/pdns.d/pdns.local.gsqlite3.conf b/powerdns/pdns.d/pdns.local.gsqlite3.conf
new file mode 100644
index 0000000..ccde43f
--- /dev/null
+++ b/powerdns/pdns.d/pdns.local.gsqlite3.conf
@@ -0,0 +1,8 @@
1# Configuration for gsqlite
2#
3# Launch gsqlite3
4launch+=gsqlite3
5
6# Database location
7gsqlite3-database=/var/lib/powerdns/pdns.sqlite3
8gsqlite3-dnssec=on
diff --git a/powerdns/powerdns.sqlite3 b/powerdns/powerdns.sqlite3
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/powerdns/powerdns.sqlite3
diff --git a/samizdat-ssh-command b/samizdat-ssh-command
new file mode 100755
index 0000000..a03b554
--- /dev/null
+++ b/samizdat-ssh-command
@@ -0,0 +1,324 @@
1#!/bin/dash
2default_command="$HOME/samizdat-default-command"
3if ! [ "$default_command" ] || ! [ -e "$default_command" ]
4then
5 default_command=password_authentication
6fi
7
8authorize()
9{
10 local authtype authdata forced_command comment authorized_keys_line
11 [ "$SSH_USER_AUTH" -a -f "$SSH_USER_AUTH" ] || return
12 read authtype authdata < "$SSH_USER_AUTH" || return
13 [ "$authtype" = publickey ] || return
14
15 forced_command="command=\"${0} authorize-full-access\",no-port-forwarding"
16 comment="samizdat: password-authenticated from ${SSH_CONNECTION%% *}"
17
18 authorized_keys_line="$forced_command $authdata $comment"
19 sentinel='Samizdat - YES WE CAN'
20
21 su - "$USER" -c 'mkdir -p "$HOME"/.ssh; touch "$HOME"/.ssh/authorized_keys' &&
22 add_before_sentinel "$sentinel" \
23 "$authorized_keys_line" \
24 "$HOME"/.ssh/authorized_keys
25}
26
27add_before_sentinel()
28{
29 local sentinel="$1" add_me="$2" target="$3"
30 sed -i.samizdat~ \
31 -e "/$sentinel/i $add_me" \
32 "$target"
33}
34
35password_authentication()
36{
37 [ "$USER" ] || { echo 'Error: no $USER' >&2; exit 1; }
38 [ "$SSH_CLIENT_FINGERPRINT" ] || { echo 'Error: no $SSH_CLIENT_FINGERPRINT' >&2; exit 1; }
39
40 tty=$(tty) && [ "$tty" != 'not a tty' ] || tty=
41
42 if [ "$SSH_ORIGINAL_COMMAND" ]; then
43 msg='You are not authorized to execute the command: %s\n'
44 if ! [ "$tty" ]; then
45 msg="$msg"'To authorize your public key via password, reconnect without a command, or with a terminal attached.\n'
46 msg="$msg"'To attach a terminal, use the "-t" option to ssh.\n'
47 else
48 msg="$msg"'To authorize your public key and execute the command, enter your password.\n'
49 fi
50 printf "\n$msg\n" "$SSH_ORIGINAL_COMMAND" >&2
51 if ! [ "$tty" ]; then
52 exit 1
53 fi
54 else
55 msg='You are not authorized to log in.\n'
56 msg="$msg"'To authorize your public key and log in, enter your password.\n'
57 printf "\n$msg\n" >&2
58 fi
59 authorize || exit $?
60 # TODO: blacklist after too many authentication failures
61 if [ "$SSH_ORIGINAL_COMMAND" ]; then
62 exec "$SSH_ORIGINAL_COMMAND"
63 else
64 exec $(getent passwd "$USER"|cut -d: -f7) -i
65 fi
66 exit $? # exec failed
67}
68
69die() { echo "Error: $*" >&2; exit 1; }
70
71dequote()
72{
73 # Sorry about the slashes. The perl would be: s{ \\(.) | '([^']+)' }{ $1$2 }gx
74 git_dir=$(echo -n "$git_dir" | sed -e "s/\\\\\\(.\\)\\|'\\([^']\\+\\)'/\\1\\2/g")
75}
76
77homedir_expand()
78{
79 git_dir=$(homedir_expand_arg "$git_dir") &&
80 [ "$git_dir" ] || die "Could not expand home directory. HOME=$HOME, USER=$USER, id=$(id)"
81}
82
83homedir_expand_arg()
84{
85 [ "$HOME" ] || die '$HOME is not set.'
86 case "$1" in
87 \~) echo "$HOME";;
88 \~/*) echo "${HOME}${1#\~}";;
89 \~*)
90 local u
91 u=${1#\~}
92 u=${u%%/*}
93 u=$(getent passwd "$u"|cut -f6 -d:) && [ "$u" ] || return 1
94 echo "$u/${1#*/}";;
95 /*) echo "$1";;
96 *) echo "$HOME/$1";;
97 esac
98}
99
100initialize_git()
101{
102 local git_dir="$1" anonymous="$2"
103 if ! [ -e "$git_dir" ]; then
104 mkdir -p "$(dirname "$git_dir")"
105 git init --bare "$git_dir" >&2
106 if [ "$anonymous" ]; then
107 git --git-dir "$git_dir" config samizdat.allow-anonymous-access true
108 git --git-dir "$git_dir" config samizdat.anonymous-ssh-owner "$anonymous"
109 fi
110 fi
111}
112
113is_gitdir() { git rev-parse --resolve-git-dir "$1" >/dev/null 2>&1; }
114
115deny() { echo 'Error: permission denied.' >&2; exit 1; }
116
117valid_new_public_repo()
118{
119 local git_dir="$1"
120 [ ! -e "$git_dir" ] || return
121 [ "$HOME" -a -d "$HOME"/public_git ] || return
122 local dirname="$(dirname "$git_dir")"
123
124 case "$git_dir" in
125 *.git) ;;
126 *)
127 echo 'Error: public repos must be named *.git' >&2
128 return 1 ;;
129 esac
130
131 case "$dirname" in
132 $HOME/public_git) return 0 ;;
133 $HOME/public_git/*)
134 # Ensure that no parent directory is named *.git
135 # Also enforce a maximum depth of 4.
136 # Valid: public_git/a/b/c/d.git
137 # Invalid: public_git/a/b/c/d/e.git
138 local n relative="${git_dir#$HOME/public_git/}"
139 for n in 1 2 3 4; do
140 local topmost="${relative%%/*}"
141 case "$topmost" in
142 "$relative") return 0;;
143 *.git) return 1;;
144 esac
145 relative=${relative#$topmost/}
146 done
147 echo 'Error: directories nest too deep' >&2
148 return 1
149 ;;
150 *) return 1 ;;
151 esac
152}
153
154check_if_ssh_user_owns_repository()
155{
156 git --git-dir "$git_dir" config --get-all samizdat.anonymous-ssh-owner | grep -xqF "$SSH_CLIENT_FINGERPRINT"
157}
158ssh_user_owns_repository()
159{
160 if [ -z "$SSH_USER_OWNS_REPOSITORY" ]; then
161 check_if_ssh_user_owns_repository
162 SSH_USER_OWNS_REPOSITORY=$?
163 fi
164 return $SSH_USER_OWNS_REPOSITORY
165}
166
167is_public_repository()
168{
169 case "$git_dir" in
170 */../*) false;;
171 "$HOME"/public_git/*) true;;
172 *) false;;
173 esac
174}
175
176authorized()
177{
178 # TODO: check SSH_CLIENT_FINGERPRINT against a blacklist
179 ssh_user_owns_repository && return
180 is_public_repository && return
181 test "$(git --git-dir "$1" config --bool --get samizdat.allow-anonymous-access)" = true 2>/dev/null && return 0
182 # TODO: check SSH_CLIENT_FINGERPRINT against a whitelist
183}
184
185maybe_initialize_heads()
186{
187 [ "$GIT_NAMESPACE" ] || die 'Programmer error'
188 heads=$git_dir/refs/namespaces/$GIT_NAMESPACE/refs/heads
189 mkdir -p "$heads"
190 found_file=$(find "$heads" -type f -print -quit)
191 [ "$found_file" ] && return
192 [ -e "$git_dir/refs/heads/master" ] && cp "$git_dir/refs/heads/master" "$heads"
193 # TODO: copy actual file 'HEAD' and whatever it references
194}
195
196
197if [ "$1" = "authorize-full-access" ]; then
198 case "$SSH_ORIGINAL_COMMAND" in
199 git-receive-pack\ *)
200 git_cmd=git-receive-pack
201 git_dir="${SSH_ORIGINAL_COMMAND#git-receive-pack }"
202 dequote
203 homedir_expand
204 initialize_git "$git_dir"
205 exec "$git_cmd" "$git_dir"
206 ;;
207 "")
208 shell=$(getent passwd $USER|cut -d: -f7)
209 argv0=-${shell##*/}
210 if which chpst >/dev/null 2>&1; then
211 exec chpst -b "$argv0" "$shell"
212 else
213 exec "$shell"
214 fi
215 ;;
216 *)
217 exec /bin/sh -c "$SSH_ORIGINAL_COMMAND"
218 ;;
219 esac
220 exit
221fi
222
223eval "$(samizdat-ssh-uid)" || die eval
224
225if [ $# -gt 0 ]
226then
227 exec "$@"
228 exit
229fi
230
231# TODO: call password_authentication on all authorization failures
232
233#echo "SSH_ORIGINAL_COMMAND=$SSH_ORIGINAL_COMMAND" >&2
234case "$SSH_ORIGINAL_COMMAND" in
235 git-upload-pack\ *|git-receive-pack\ *)
236 # set three variables
237 # 1. git_cmd
238 # 2. git_dir
239 # 3. git_ns (optional)
240
241 git_cmd=${SSH_ORIGINAL_COMMAND%%\ *}
242 git_dir=${SSH_ORIGINAL_COMMAND#*\ }
243
244 dequote
245 homedir_expand
246
247 case "$git_dir" in
248 $HOME/git_namespace/*/public_git/*)
249 git_ns_subdir=${git_dir#$HOME/git_namespace/}
250 git_ns=${git_ns_subdir%%/*}
251 git_dir=$HOME/${git_ns_subdir#*/}
252 ;;
253 esac
254
255 ;;
256 rsync\ --server\ --sender\ -de.LsfxC\ .\ public_git/|rsync\ --server\ --sender\ -de.LsfxC\ .\ public_git/|rsync\ --server\ --sender\ -de.Lsf\ .\ public_git/)
257 #echo "$SSH_ORIGINAL_COMMAND" >&2
258 [ -d "$HOME"/public_git ] || { password_authentication; exit 1; }
259 exec $SSH_ORIGINAL_COMMAND
260 #exec rrsync -ro "$HOME"/public_git
261 exit 1
262 ;;
263 rsync\ --server\ --sender\ *)
264 #echo "$SSH_ORIGINAL_COMMAND" >&2
265 [ -d "$HOME"/public_rsync ] || { password_authentication; exit 1; }
266 exec rrsync -ro "$HOME"/public_rsync
267 exit 1
268 ;;
269 rsync\ --server\ *)
270 [ -d "$HOME"/incoming_rsync -a "${SSH_CLIENT_FINGERPRINT}" ] || { password_authentication; exit 1; }
271 destdir=$HOME/incoming_rsync/$SSH_CLIENT_FINGERPRINT/
272 mkdir -p "$destdir" && exec rrsync "$destdir"
273 exit 1
274 ;;
275 *)
276 #password_authentication
277 $default_command
278 exit
279 ;;
280esac
281
282if [ "$git_cmd" = 'git-upload-pack' ]; then
283 case "$git_dir" in
284 $HOME/public_git/*|public_git/*)
285 is_gitdir "$git_dir" || git_dir="$git_dir/.git"
286 if ! is_gitdir "$git_dir"; then
287 # git rev-parse --resolve-git-dir "${git_dir%/.git}" # show git's error message
288 deny
289 fi
290 if [ "$git_ns" -a -e "$git_dir/refs/namespaces/$git_ns" ]; then
291 export GIT_NAMESPACE="$git_ns"
292 # maybe_initialize_heads
293 fi
294 exec "$git_cmd" "$git_dir"
295 ;;
296 esac
297
298elif [ "$git_cmd" = 'git-receive-pack' ]; then
299
300 if [ ! -d "$git_dir" ]; then
301 if valid_new_public_repo "$git_dir"; then
302 initialize_git "$git_dir" "$SSH_CLIENT_FINGERPRINT"
303 else
304 deny
305 fi
306 fi
307
308fi
309
310if authorized "$git_dir"; then
311 if [ "$git_cmd" = 'git-receive-pack' ]; then
312 if ! ssh_user_owns_repository
313 then
314 export GIT_NAMESPACE="$SSH_CLIENT_FINGERPRINT"
315 maybe_initialize_heads
316 printf '%s:%s\n' 'd@cryptonomic.net' "git_namespace/$GIT_NAMESPACE/${git_dir#${HOME}/}" >&2
317 fi
318 fi
319 exec "$git_cmd" "$git_dir"
320else
321 $default_command
322 exit
323 # echo 'Error: git access is unauthorized' >&2; exit 1 # unreached
324fi
diff --git a/samizdat-ssh-uid b/samizdat-ssh-uid
new file mode 100755
index 0000000..2b4b311
--- /dev/null
+++ b/samizdat-ssh-uid
@@ -0,0 +1,39 @@
1#!/bin/dash
2
3die() { echo "$0: Error: $*" >&2; exit 1; }
4
5[ "$SSH_USER_AUTH" ] || die "not defined: \$SSH_USER_AUTH"
6[ -f "$SSH_USER_AUTH" ] || die "file does not exist: \$SSH_USER_AUTH=${SSH_USER_AUTH}"
7
8PEMFILE="${SSH_USER_AUTH}.tmp"
9
10sed -ne 's/^publickey //p' < "${SSH_USER_AUTH}" > "${PEMFILE}" || die "could not rewrite SSH_USER_AUTH file"
11
12SSH_CLIENT_FINGERPRINT=$(ssh-keygen -r . -f "${PEMFILE}" | sed -ne 's/^. IN SSHFP [0-9]* 2 //p') &&
13 [ "$SSH_CLIENT_FINGERPRINT" ] || die "could not determine ssh client fingerprint"
14
15read keytype keydata < "${PEMFILE}" || die "reading from PEMFILE=$PEMFILE"
16case "$keytype" in
17 ssh-rsa|ssh-dss|ecdsa-sha2-nistp256|ssh-ed25519)
18 domain=$keytype.cryptonomic.net ;;
19 *)
20 die "Unsupported key type: $keytype" ;;
21esac
22
23if [ "$1" = '--copy-pem' -a "$2" ]
24then
25 if [ -d "$2" ] || mkdir "$2"
26 then
27 mv "${PEMFILE}" "$2"/${SSH_CLIENT_FINGERPRINT}.${keytype}.pem
28 fi
29else
30 rm -f "${PEMFILE}"
31fi
32
33env -i \
34 SSH_CLIENT_FINGERPRINT="$SSH_CLIENT_FINGERPRINT" \
35 SSH_CLIENT_KEYTYPE="$keytype" \
36 SSH_CLIENT_DOMAIN="$domain" \
37 SSH_CLIENT_PEMFILE="$PEMFILE" \
38 SSH_CLIENT_KEYDATA="$keydata"
39
diff --git a/sources.list.d/pdns.list b/sources.list.d/pdns.list
new file mode 100644
index 0000000..795d281
--- /dev/null
+++ b/sources.list.d/pdns.list
@@ -0,0 +1 @@
deb http://repo.powerdns.com/debian stretch-auth-42 main