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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
|
#!/usr/bin/perl
# Call like this:
# TSH_VERBOSE=1 TSH_ERREXIT=1 HARNESS_ACTIVE=1 GITOLITE_TEST=y prove t/ukm.t
use strict;
use warnings;
# this is hardcoded; change it if needed
use lib "src/lib";
use Gitolite::Common;
use Gitolite::Test;
# basic tests using ssh
# ----------------------------------------------------------------------
my $bd = `gitolite query-rc -n GL_BINDIR`;
my $h = $ENV{HOME};
my $ab = `gitolite query-rc -n GL_ADMIN_BASE`;
my $pd = "$bd/../t/keys"; # source for pubkeys
umask 0077;
_mkdir( "$h/.ssh", 0700 ) if not -d "$h/.ssh";
try "plan 204";
# Reset everything.
# Only admin and u1, u2, and u3 keys are available initially
# Keys u4, u5, and u6 are used as guests later.
# For easy access, we put the keys into ~/.ssh/, though.
try "
rm -f $h/.ssh/authorized_keys; ok or die 1
cp $pd/u[1-6]* $h/.ssh; ok or die 2
cp $pd/admin* $h/.ssh; ok or die 3
cp $pd/config $h/.ssh; ok or die 4
cat $h/.ssh/config
perl s/%USER/$ENV{USER}/
put $h/.ssh/config
mkdir $ab/keydir; ok or die 5
cp $pd/u[1-3].pub $ab/keydir; ok or die 6
cp $pd/admin.pub $ab/keydir; ok or die 7
";
# Put the keys into ~/.ssh/authorized_keys
system("gitolite ../triggers/post-compile/ssh-authkeys");
# enable user key management in a simple form.
# Guest key managers can add keyids looking like email addresses, but
# cannot add emails containing example.com or hemmecke.org.
system("sed -i \"s/.*ENABLE =>.*/'UKM_CONFIG'=>{'FORBIDDEN_GUEST_PATTERN'=>'example.com|hemmecke.org'}, ENABLE => ['ukm',/\" $h/.gitolite.rc");
# super-key-managers can add/del any key
# super-key-managers should in fact agree with people having write
# access to gitolite-admin repo.
# guest-key-managers can add/del guest keys
confreset; confadd '
@guest-key-managers = u2 u3
@creators = u2 u3
repo pub/CREATOR/..*
C = @creators
RW+ = CREATOR
RW = WRITERS
R = READERS
';
# Populate the gitolite-admin/keydir in the same way as it was used for
# the initialization of .ssh/authorized_keys above.
try "
mkdir keydir; ok or die 8
cp $pd/u[1-3].pub keydir; ok or die 9;
cp $pd/admin.pub keydir; ok or die 10;
git add conf keydir; ok
git commit -m ukm; ok; /master.* ukm/
";
# Activate new config data.
try "PUSH admin; ok; gsh; /master -> master/; !/FATAL/" or die text();
# Check whether the above setup yields the expected behavior for ukm.
# The admin is super-key-manager, thus can manage every key.
try "
ssh admin ukm; ok; /Hello admin, you manage the following keys:/
/ admin +admin/
/ u1 +u1/
/ u2 +u2/
/ u3 +u3/
";
# u1 isn't a key manager, so shouldn't be above to manage keys.
try "ssh u1 ukm; !ok; /FATAL: You are not a key manager./";
# u2 and u3 are guest key managers, but don't yet manage any key.
try "ssh u2 ukm; ok"; cmp "Hello u2, you manage the following keys:\n\n\n";
try "ssh u3 ukm; ok"; cmp "Hello u3, you manage the following keys:\n\n\n";
###################################################################
# Unknows subkommands abort ukm.
try "ssh u2 ukm fake; !ok; /FATAL: unknown ukm subcommand: fake/";
###################################################################
# Addition of keys.
# If no data is provided on stdin, we don't block, but rather timeout
# after one second and abort the program.
try "ssh u2 ukm add u4\@example.org; !ok; /FATAL: missing public key data/";
# If no keyid is given, we cannot add a key.
try "ssh u2 ukm add; !ok; /FATAL: keyid required/";
try "
DEF ADD = cat $pd/%1.pub|ssh %2 ukm add %3
DEF ADDOK = ADD %1 %2 %3; ok
DEF ADDNOK = ADD %1 %2 %3; !ok
DEF FP = ADDNOK u4 u2 %1
DEF FORBIDDEN_PATTERN = FP %1; /FATAL: keyid not allowed:/
";
# Neither a guest key manager nor a super key manager can add keys that have
# double dot in their keyid. This is hardcoded to forbid paths with .. in it.
try "
ADDNOK u4 u2 u4\@hemmecke..org; /Not allowed to use '..' in keyid./
ADDNOK u4 admin u4\@hemmecke..org; /Not allowed to use '..' in keyid./
ADDNOK u4 admin ./../.myshrc; /Not allowed to use '..' in keyid./
";
# guest-key-managers can only add keys that look like emails.
try "
FORBIDDEN_PATTERN u4
FORBIDDEN_PATTERN u4\@example
FORBIDDEN_PATTERN u4\@foo\@example.org
# No support for 'old style' multiple keys.
FORBIDDEN_PATTERN u4\@example.org\@foo
# No path delimiter in keyid
FORBIDDEN_PATTERN foo/u4\@example.org
# Certain specific domains listed in FORBIDDEN_GUEST_PATTERN are forbidden.
# Note that also u4\@example-com would be rejected, because MYDOMAIN
# contains a regular expression --> I don't care.
FORBIDDEN_PATTERN u4\@example.com
FORBIDDEN_PATTERN u4\@hemmecke.org
";
# Accept one guest key.
try "ADDOK u4 u2 u4\@example.org";
try "ssh u2 ukm; ok; /Hello u2, you manage the following keys:/
/ u4\@example.org *u4\@example.org/";
# Various ways how a key must be rejected.
try "
# Cannot add the same key again.
ADDNOK u4 u2 u4\@example.org; /FATAL: cannot override existing key/
# u2 can also not add u4.pub under another keyid
ADDNOK u4 u2 u4\@example.net; /FATAL: cannot add key/
/Same key is already available under another userid./
# u2 can also not add another key under the same keyid.
ADDNOK u5 u2 u4\@example.org; /FATAL: cannot override existing key/
# Also u3 cannot not add another key under the same keyid.
ADDNOK u5 u3 u4\@example.org
/FATAL: cannot add another public key for an existing user/
# And u3 cannot not add u4.pub under another keyid.
ADDNOK u4 u3 u4\@example.net; /FATAL: cannot add key/
/Same key is already available under another userid./
# Not even the admin can add the same key u4 under a different userid.
ADDNOK u4 admin u4\@example.net; /FATAL: cannot add key/
/Same key is already available under another userid./
/Found .* u4\@example.org/
# Super key managers cannot add keys that start with @.
# We don't care about @ in the dirname, though.
ADDNOK u4 admin foo/\@ex.net; /FATAL: cannot add key that starts with \@/
ADDNOK u4 admin foo/\@ex; /FATAL: cannot add key that starts with \@/
ADDNOK u4 admin \@ex.net; /FATAL: cannot add key that starts with \@/
ADDNOK u4 admin \@ex; /FATAL: cannot add key that starts with \@/
";
# But u3 can add u4.pub under the same keyid.
try "ADDOK u4 u3 u4\@example.org";
try "ssh u3 ukm; ok; /Hello u3, you manage the following keys:/
/ u4\@example.org *u4\@example.org/";
# The admin can add multiple keys for the same userid.
try "
ADDOK u5 admin u4\@example.org
ADDOK u5 admin u4\@example.org\@home
ADDOK u5 admin laptop/u4\@example.org
ADDOK u5 admin laptop/u4\@example.org\@home
";
# And admin can also do this for other guest key managers. Note,
# however, that the gitolite-admin must be told where the
# GUEST_DIRECTORY is. But he/she could find out by cloning the
# gitolite-admin repository and adding the same key directly.
try "
ADDOK u5 admin zzz/guests/u2/u4\@example.org\@foo
ADDOK u6 admin zzz/guests/u3/u6\@example.org
";
try "ssh admin ukm; ok"; cmp "Hello admin, you manage the following keys:
fingerprint userid keyid
a4:d1:11:1d:25:5c:55:9b:5f:91:37:0e:44:a5:a5:f2 admin admin
00:2c:1f:dd:a3:76:5a:1e:c4:3c:01:15:65:19:a5:2e u1 u1
69:6f:b5:8a:f5:7b:d8:40:ce:94:09:a2:b8:95:79:5b u2 u2
26:4b:20:24:98:a4:e4:a5:b9:97:76:9a:15:92:27:2d u3 u3
78:cf:7e:2b:bf:18:58:54:23:cc:4b:3d:7e:f4:63:79 u4\@example.org laptop/u4\@example.org
78:cf:7e:2b:bf:18:58:54:23:cc:4b:3d:7e:f4:63:79 u4\@example.org laptop/u4\@example.org\@home
78:cf:7e:2b:bf:18:58:54:23:cc:4b:3d:7e:f4:63:79 u4\@example.org u4\@example.org
78:cf:7e:2b:bf:18:58:54:23:cc:4b:3d:7e:f4:63:79 u4\@example.org u4\@example.org\@home
8c:a6:c0:a5:71:85:0b:89:d3:08:97:22:ae:95:e1:bb u4\@example.org zzz/guests/u2/u4\@example.org
78:cf:7e:2b:bf:18:58:54:23:cc:4b:3d:7e:f4:63:79 u4\@example.org zzz/guests/u2/u4\@example.org\@foo
8c:a6:c0:a5:71:85:0b:89:d3:08:97:22:ae:95:e1:bb u4\@example.org zzz/guests/u3/u4\@example.org
fc:0f:eb:52:7a:d2:35:da:89:96:f5:15:0e:85:46:e7 u6\@example.org zzz/guests/u3/u6\@example.org
\n\n";
# Now, u2 has two keys in his directory, but u2 can manage only one of
# them, since the one added by the admin has two @ in it. Thus the key
# added by admin is invisible to u2.
try "ssh u2 ukm; ok"; cmp "Hello u2, you manage the following keys:
fingerprint userid keyid
8c:a6:c0:a5:71:85:0b:89:d3:08:97:22:ae:95:e1:bb u4\@example.org u4\@example.org
\n\n";
# Since admin added key u6@example.org to the directory of u2, u2 is
# also able to see it and, in fact, to manage it.
try "ssh u3 ukm; ok"; cmp "Hello u3, you manage the following keys:
fingerprint userid keyid
8c:a6:c0:a5:71:85:0b:89:d3:08:97:22:ae:95:e1:bb u4\@example.org u4\@example.org
fc:0f:eb:52:7a:d2:35:da:89:96:f5:15:0e:85:46:e7 u6\@example.org u6\@example.org
\n\n";
###################################################################
# Deletion of keys.
try "
DEF DEL = ssh %1 ukm del %2
DEF DELOK = DEL %1 %2; ok
DEF DELNOK = DEL %1 %2; !ok
DEF DELNOMGR = DELNOK %1 %2; /FATAL: You are not managing the key /
";
# Deletion requires a keyid.
try "ssh u3 ukm del; !ok; /FATAL: keyid required/";
# u3 can, of course, not remove any unmanaged key.
try "DELNOMGR u3 u2";
# But u3 can delete u4@example.org and u6@example.org. This will, of course,
# not remove the key u4@example.org that u2 manages.
try "
DELOK u3 u4\@example.org
DELOK u3 u6\@example.org
";
# After having deleted u4@example.org, u3 cannot remove it again,
# even though, u2 still manages that key.
try "DELNOMGR u3 u4\@example.org";
# Of course a super-key-manager can remove any (existing) key.
try "
DELOK admin zzz/guests/u2/u4\@example.org
DELNOK admin zzz/guests/u2/u4\@example.org
/FATAL: You are not managing the key zzz/guests/u2/u4\@example.org./
DELNOK admin zzz/guests/u2/u4\@example.org\@x
/FATAL: You are not managing the key zzz/guests/u2/u4\@example.org./
DELOK admin zzz/guests/u2/u4\@example.org\@foo
";
# As the admin could do that via pushing to the gitolite-admin manually,
# it's also allowed to delete even non-guest keys.
try "DELOK admin u3";
# Let's clean the environment again.
try "
DELOK admin laptop/u4\@example.org\@home
DELOK admin laptop/u4\@example.org
DELOK admin u4\@example.org\@home
DELOK admin u4\@example.org
ADDOK u3 admin u3
";
# Currently the admin has just one key. It cannot be removed.
# But after adding another key, deletion should work fine.
try "
DELNOK admin admin; /FATAL: You cannot delete your last key./
ADDOK u6 admin second/admin; /Adding new public key for admin./
DELOK admin admin
DELNOK u6 admin; /FATAL: You are not managing the key admin./
DELNOK u6 second/admin; /FATAL: You cannot delete your last key./
ADDOK admin u6 admin; /Adding new public key for admin./
DELOK u6 second/admin
";
###################################################################
# Selfkey management.
# If self key management is not switched on in the .gitolite.rc file,
# it's not allowed at all.
try "ssh u2 ukm add \@second; !ok; /FATAL: selfkey management is not enabled/";
# Let's enable it.
system("sed -i \"/'UKM_CONFIG'=>/s/=>{/=>{'SELFKEY_MANAGEMENT'=>1,/\" $h/.gitolite.rc");
# And add self-key-managers to gitolite.conf
# chdir("../gitolite-admin") or die "in `pwd`, could not cd ../g-a";
try "glt pull admin origin master; ok";
put "|cut -c5- > conf/gitolite.conf", '
repo gitolite-admin
RW+ = admin
repo testing
RW+ = @all
@guest-key-managers = u2 u3
@self-key-managers = u1 u2
@creators = u2 u3
repo pub/CREATOR/..*
C = @creators
RW+ = CREATOR
RW = WRITERS
R = READERS
';
try "
git add conf keydir; ok
git commit -m selfkey; ok; /master.* selfkey/
";
try "PUSH admin; ok; gsh; /master -> master/; !/FATAL/" or die text();
# Now we can start with the tests.
# Only self key managers are allowed to use selfkey management.
# See variable @self-key-managers.
try "ssh u3 ukm add \@second; !ok; /FATAL: You are not a selfkey manager./";
# Cannot add keyid that are not alphanumeric.
try "ssh u1 ukm add \@second-key; !ok; /FATAL: keyid not allowed:/";
# Add a second key for u1, but leave it pending by not feeding in the
# session key. The new user can login, but he/she lives under a quite
# random gl_user name and thus is pretty much excluded from everything
# except permissions given to @all. If this new id calls ukm without
# providing the session key, this (pending) key is automatically
# removed from the system.
# If a certain keyid is in the system, then it cannot be added again.
try "
ADDOK u4 u1 \@second
ssh admin ukm; ok; /u1 zzz/self/u1/zzz-add-[a-z0-9]{32}-second-u1/
ssh u1 ukm; ok; /u1 \@second .pending add./
ADDNOK u4 u1 \@second; /FATAL: keyid already in use: \@second/
ssh u4 ukm; ok; /pending keyid deleted: \@second/
ssh admin ukm; ok; !/zzz/; !/second/
";
# Not providing a proper ssh public key will abort. Providing a good
# ssh public key, which is not a session key makes the key invalid.
# The key will, therefore, be deleted by this operation.
try "
ADDOK u4 u1 \@second
echo fake|ssh u4 ukm; !ok; /FATAL: does not seem to be a valid pubkey/
cat $pd/u5.pub | ssh u4 ukm; ok;
/session key not accepted/
/pending keyid deleted: \@second/
";
# True addition of a new selfkey is done via piping it to a second ssh
# call that uses the new key to call ukm. Note that the first ssh must
# have completed its job before the second ssh is able to successfully
# log in. This can be done via sleep or via redirecting to a file and
# then reading from it.
try "
# ADDOK u4 u1 \@second | (sleep 2; ssh u4 ukm); ok
ADD u4 u1 \@second > session; ok
cat session | ssh u4 ukm; ok; /pending keyid added: \@second/
";
# u1 cannot add his/her initial key, since that key can never be
# confirmed via ukm, so it is forbidden altogether. In fact, u1 is not
# allowed to add any key twice.
try "
ADDNOK u1 u1 \@first
/FATAL: You cannot add a key that already belongs to you./
ADDNOK u4 u1 \@first
/FATAL: You cannot add a key that already belongs to you./
";
# u1 also can add more keys, but not under an existing keyid. That can
# be done by any of his/her identities (here we choose u4).
try "
ADDNOK u5 u1 \@second; /FATAL: keyid already in use: \@second/
ADD u5 u4 \@third > session; ok
cat session | ssh u5 ukm; ok; /pending keyid added: \@third/
";
# u2 cannot add the same key, but is allowed to use the same name (@third).
try "
ADDNOK u5 u2 \@third; /FATAL: cannot add key/
/Same key is already available under another userid./
ADD u6 u2 \@third > session; ok
cat session | ssh u6 ukm; ok; /pending keyid added: \@third/
";
# u6 can schedule his/her own key for deletion, but cannot actually
# remove it. Trying to do so results in bringing back the key. Actual
# deletion must be confirmed by another key.
try "
ssh u6 ukm del \@third; /prepare deletion of key \@third/
ssh u2 ukm; ok; /u2 \@third .pending del./
ssh u6 ukm; ok; /undo pending deletion of keyid \@third/
ssh u6 ukm del \@third; /prepare deletion of key \@third/
ssh u2 ukm del \@third; ok; /pending keyid deleted: \@third/
";
# While in pending-deletion state, it's forbidden to add another key
# with the same keyid. It's also forbidden to add a key with the same
# fingerprint as the to-be-deleted key).
# A new key under another keyid, is OK.
try "
ssh u1 ukm del \@third; /prepare deletion of key \@third/
ADDNOK u4 u1 \@third; /FATAL: keyid already in use: \@third/
ADDNOK u5 u1 \@fourth;
/FATAL: You cannot add a key that already belongs to you./
ADD u6 u1 \@fourth > session; ok
ssh u1 ukm; ok;
/u1 \@second/
/u1 \@fourth .pending add./
/u1 \@third .pending del./
";
# We can remove a pending-for-addition key (@fourth) by logging in
# with a non-pending key. Trying to do anything with key u5 (@third)
# will just bring it back to its normal state, but not change the
# state of any other key. As already shown above, using u6 (@fourth)
# without a proper session key, would remove it from the system.
# Here we want to demonstrate that key u1 can delete u6 immediately.
try "ssh u1 ukm del \@fourth; /pending keyid deleted: \@fourth/";
# The pending-for-deletion key @third can also be removed via the u4
# (@second) key.
try "ssh u4 ukm del \@third; ok; /pending keyid deleted: \@third/";
# Non-existing selfkeys cannot be deleted.
try "ssh u4 ukm del \@x; !ok; /FATAL: You are not managing the key \@x./";
|