GSS=true
GSS_KRB5=true
+# Overwrite RUNAS command to use su - instead,
+# to initialize the process more completely.
+# This is required to get proper access to keyrings.
+RUNAS="runas_su $(id -n -u $RUNAS_ID)"
+
check_krb_env() {
which klist || skip "Kerberos env not setup"
which kinit || skip "Kerberos env not setup"
set_flavor_all krb5p
-test_1() {
+test_1a() {
local file=$DIR/$tdir/$tfile
mkdir $DIR/$tdir || error "mkdir $DIR/$tdir failed"
$RUNAS touch $file || error "should not fail"
[ -f $file ] || error "$file not found"
}
-run_test 1 "access with or without krb5 credential"
+run_test 1a "access with or without krb5 credential"
+
+test_1b() {
+ local file=$DIR/$tdir/$tfile
+ local lgssconf=/etc/request-key.d/lgssc.conf
+ local clients=$CLIENTS
+ local realm
+
+ [ -z $clients ] && clients=$HOSTNAME
+ zconf_umount_clients $clients $MOUNT || error "umount clients failed"
+
+ echo "stop gss daemons..."
+ stop_gss_daemons
+
+ # get local realm from krb5.conf, assume the same for all nodes
+ realm=$(grep default_realm /etc/krb5.conf | awk '{print $3}')
+
+ # add -R option to lgss_keyring on local client
+ cp $lgssconf $TMP/lgssc.conf
+ stack_trap "yes | cp $TMP/lgssc.conf $lgssconf" EXIT
+ sed -i s+lgss_keyring+\&\ \-R\ $realm+ $lgssconf
+
+ # add -R option to lsvcgssd
+ echo "bring up gss daemons..."
+ start_gss_daemons '' '' "-R $realm"
+ stack_trap "stop_gss_daemons ; start_gss_daemons" EXIT
+
+ zconf_mount_clients $clients $MOUNT || error "mount clients failed"
+
+ mkdir $DIR/$tdir || error "mkdir $DIR/$tdir failed"
+ chmod 0777 $DIR/$tdir || error "chmod $DIR/$tdir failed"
+ $RUNAS touch $file || error "touch $file failed"
+ [ -f $file ] || error "$file not found"
+}
+run_test 1b "Use specified realm"
test_2() {
local file1=$DIR/$tdir/$tfile-1
$RUNAS $LFS flushctx -k -r $MOUNT || error "can't flush context"
echo "destroyed credentials/contexs for $RUNAS_ID"
$RUNAS $CHECKSTAT -p 0666 $file && error "checkstat succeed"
- kill -s 10 $OPPID
+ kill -s 10 $(pgrep -u $USER0 $MULTIOP)
wait $OPPID || error "read file data failed"
echo "read file data OK"
test_5() {
local file1=$DIR/$tdir/$tfile-1
local file2=$DIR/$tdir/$tfile-2
+ local file3=$DIR/$tdir/$tfile-3
local wait_time=$((TIMEOUT + TIMEOUT / 2))
mkdir $DIR/$tdir || error "mkdir $DIR/$tdir failed"
$RUNAS touch $file1 || error "can't touch $file1"
[ -f $file1 ] || error "$file1 not found"
+ # flush context
+ $RUNAS $LFS flushctx $MOUNT || error "can't flush context (1)"
+
# stop lsvcgssd
send_sigint $(comma_list $(mdts_nodes)) $LSVCGSSD
sleep 5
check_gss_daemon_nodes $(comma_list $(mdts_nodes)) $LSVCGSSD &&
- error "$LSVCGSSD still running"
+ error "$LSVCGSSD still running (1)"
+
+ # daemon should restart automatically, at least on newer servers
+ $RUNAS touch $file2
+ if [ $? -ne 0 ]; then
+ echo "$RUNAS touch $file2 failed"
+ (( MDS1_VERSION < $(version_code 2.15.61) )) ||
+ error "$LSVCGSSD should restart automatically"
+ else
+ echo "$RUNAS touch $file2 succeeded"
+ fi
- # flush context, and touch
- $RUNAS $LFS flushctx -k -r $MOUNT || error "can't flush context (1)"
- restore_krb5_cred
- $RUNAS touch $file2 && error "should fail without $LSVCGSSD"
+ # flush context
+ if (( MDS1_VERSION >= $(version_code 2.15.61) )); then
+ $RUNAS $LFS flushctx $MOUNT || error "can't flush context (2)"
+ fi
+
+ # stop lsvcgssd
+ send_sigint $(comma_list $(mdts_nodes)) $LSVCGSSD
+ sleep 5
+ check_gss_daemon_nodes $(comma_list $(mdts_nodes)) $LSVCGSSD &&
+ error "$LSVCGSSD still running (2)"
# restart lsvcgssd, expect touch succeed
echo "restart $LSVCGSSD and recovering"
- start_gss_daemons $(comma_list $(mdts_nodes)) "$LSVCGSSD -vvv"
+ start_gss_daemons $(comma_list $(mdts_nodes)) $LSVCGSSD "-vvv"
sleep 5
check_gss_daemon_nodes $(comma_list $(mdts_nodes)) $LSVCGSSD
- $RUNAS $LFS flushctx -k -r $MOUNT || error "can't flush context (2)"
- restore_krb5_cred
- $RUNAS touch $file2 || error "should not fail now"
- [ -f $file2 ] || error "$file2 not found"
+ $RUNAS touch $file3 || error "should not fail now"
+ [ -f $file3 ] || error "$file3 not found"
}
-run_test 5 "lsvcgssd dead, operations fail"
+run_test 5 "lsvcgssd dead, operations pass"
test_6() {
local nfile=10
stack_trap \
"do_facet $SINGLEMDS $LCTL set_param at_history=$atoldbase" EXIT
- mkdir -p $DIR/$tdir
+ mkdir_on_mdt0 $DIR/$tdir
chmod a+w $DIR/$tdir
+ $RUNAS ls $DIR/$tdir
+ $RUNAS keyctl show @u
+ echo Flushing gss ctxs
+ $RUNAS $LFS flushctx $MOUNT || error "can't flush context on $MOUNT"
+ $RUNAS keyctl show @u
+
$LCTL dk > /dev/null
debugsave
stack_trap debugrestore EXIT
# sleep sometime in ctx handle
do_facet $SINGLEMDS $LCTL set_param fail_val=$req_delay
- #define OBD_FAIL_SEC_CTX_HDL_PAUSE 0x1204
- do_facet $SINGLEMDS $LCTL set_param fail_loc=0x1204
-
- $RUNAS $LFS flushctx -k -r $MOUNT ||
- error "can't flush context on $MOUNT"
- restore_krb5_cred
+ #define OBD_FAIL_SEC_CTX_HDL_PAUSE 0x00001204
+ #define CFS_FAIL_ONCE 0x80000000
+ do_facet $SINGLEMDS $LCTL set_param fail_loc=0x80001204
$RUNAS touch $DIR/$tdir/$tfile &
TOUCHPID=$!
echo "waiting for touch (pid $TOUCHPID) to finish..."
- sleep 2 # give it a chance to really trigger context init rpc
- do_facet $SINGLEMDS $LCTL set_param fail_loc=0
wait $TOUCHPID || error "touch should have succeeded"
+ $RUNAS keyctl show @u
$LCTL dk | grep -i "Early reply #" || error "No early reply"
}
run_test 8 "Early reply sent for slow gss context negotiation"
+test_9() {
+ local test9user=$(getent passwd $RUNAS_ID | cut -d: -f1)
+
+ $LFS mkdir -i 0 -c 1 $DIR/$tdir || error "mkdir $DIR/$tdir failed"
+ chmod 0777 $DIR/$tdir || error "chmod $DIR/$tdir failed"
+ $RUNAS ls -ld $DIR/$tdir
+
+ # Add group, and client to new group, on client only.
+ # Server is not aware.
+ groupadd -g 5000 grptest9
+ stack_trap "groupdel grptest9" EXIT
+
+ usermod -g grptest9 $test9user
+ stack_trap "usermod -g $test9user $test9user" EXIT
+ id $RUNAS_ID
+ # Thanks to Kerberos, client should not be able to create file
+ # with primary group not known on server side
+ $RUNAS touch $DIR/$tdir/fileA &&
+ error "server should not trust client's primary gid"
+ do_facet mds1 "lctl set_param mdt.*.identity_flush=-1"
+
+ do_facet mds1 groupadd -g 5000 grptest9
+ stack_trap "do_facet mds1 groupdel grptest9 || true" EXIT
+ do_facet mds1 usermod -a -G grptest9 $test9user
+ stack_trap "do_facet mds1 gpasswd -d $test9user grptest9 || true" EXIT
+ id $RUNAS_ID
+ do_facet mds1 "id $RUNAS_ID"
+ # Thanks to Kerberos, client should be able to create file
+ # with primary group taken as one of supp groups, as long as
+ # server side knows the supp groups.
+ $RUNAS touch $DIR/$tdir/fileA ||
+ error "server should know client's supp gid"
+ ls -l $DIR/$tdir
+ do_facet mds1 "lctl set_param mdt.*.identity_flush=-1"
+ do_facet mds1 gpasswd -d $test9user grptest9
+ do_facet mds1 groupdel grptest9
+ usermod -g $test9user $test9user
+
+ usermod -a -G grptest9 $test9user
+ stack_trap "gpasswd -d $test9user grptest9" EXIT
+ id $RUNAS_ID
+ $RUNAS touch $DIR/$tdir/fileB
+ ls -l $DIR/$tdir
+ # Thanks to Kerberos, client should not be able to chgrp
+ $RUNAS chgrp grptest9 $DIR/$tdir/fileB &&
+ error "server should not trust client's supp gid"
+ ls -l $DIR/$tdir
+ do_facet mds1 "lctl set_param mdt.*.identity_flush=-1"
+}
+run_test 9 "Do not trust primary and supp gids from client"
+
+test_10() {
+ local count
+
+ $LFS mkdir -i 0 -c $MDSCOUNT $DIR/$tdir ||
+ error "mkdir $DIR/$tdir failed"
+ chmod 0777 $DIR/$tdir || error "chmod $DIR/$tdir failed"
+ $RUNAS ls -ld $DIR/$tdir || error "ls -ld $DIR/$tdir failed"
+ $RUNAS grep lgssc /proc/keys
+
+ # get rid of gss context and credentials for user
+ $RUNAS $LFS flushctx -k -r $MOUNT || error "can't flush context (1)"
+ $RUNAS grep lgssc /proc/keys
+ stack_trap restore_krb5_cred EXIT
+
+ # restore krb credentials
+ restore_krb5_cred
+
+ # revoke session keyring for user and access to fs in the same su -
+ su - $(id -n -u $RUNAS_ID) -c "keyctl revoke @s && ls -ld $DIR/$tdir" ||
+ error "revoke + ls failed"
+ $RUNAS grep lgssc /proc/keys
+
+ # refcount on lgssc keys should be 2
+ for ref in $($RUNAS grep lgssc /proc/keys | awk '$4~"perm"{print $3}');\
+ do
+ [[ $ref == 2 ]] || error "bad refcnt $ref on key"
+ done
+
+ # get rid of gss context for user
+ $RUNAS $LFS flushctx $MOUNT || error "can't flush context (2)"
+ $RUNAS grep lgssc /proc/keys
+ count=$($RUNAS grep lgssc /proc/keys | grep -v "Running as" | wc -l)
+ [[ $count == 0 ]] || error "remaining $count keys for user"
+}
+run_test 10 "Support revoked session keyring"
+
#
# following tests will manipulate flavors and may end with any flavor set,
# so each test should not assume any start flavor.
stopall
# start gss daemon on mgs node
- combined_mgs_mds || start_gss_daemons $mgs_HOST "$LSVCGSSD -vvv"
+ combined_mgs_mds || start_gss_daemons $mgs_HOST $LSVCGSSD "-vvv"
# start mgs
start mgs $(mgsdevname 1) $MDS_MOUNT_OPTS
}
run_test 151 "secure mgs connection: server flavor control"
+exit_152() {
+ zconf_umount $HOSTNAME $MOUNT
+
+ # remove mgs rule
+ set_rule _mgs any any
+
+ zconf_mount $HOSTNAME $MOUNT
+ if [ "$MOUNT_2" ]; then
+ zconf_mount $HOSTNAME $MOUNT2
+ fi
+}
+
+test_152() {
+ local mount_opts
+ local count
+
+ (( MDS1_VERSION >= $(version_code 2.15.64) )) ||
+ skip "Need MDS >= 2.15.64 for user context with MGS"
+
+ stack_trap exit_152 EXIT
+
+ if is_mounted $MOUNT2; then
+ umount_client $MOUNT2 || error "umount $MOUNT2 failed"
+ fi
+
+ zconf_umount $HOSTNAME $MOUNT || error "umount $MOUNT failed"
+
+ # set mgs rule to only accept krb5p
+ set_rule _mgs any any krb5p
+
+ # start gss daemon on mgs node
+ combined_mgs_mds || start_gss_daemons $mgs_HOST $LSVCGSSD "-vvv"
+
+ # re-mount client with mgssec=krb5p
+ mount_opts="${MOUNT_OPTS:+$MOUNT_OPTS,}mgssec=krb5p"
+ zconf_mount $HOSTNAME $MOUNT $mount_opts ||
+ error "unable to mount client"
+
+ $RUNAS $LFS check mgts || error "check mgts as user failed"
+ $RUNAS grep lgssc /proc/keys
+
+ $RUNAS $LFS flushctx $MOUNT || error "flushctx as user failed"
+ $RUNAS grep lgssc /proc/keys
+ count=$($RUNAS grep lgssc /proc/keys | grep -v "Running as" | wc -l)
+ [[ $count == 0 ]] || error "remaining $count keys for user"
+}
+run_test 152 "secure mgs connection: user access"
+
+test_200() {
+ local nid=$(lctl list_nids | grep ${NETTYPE} | head -n1)
+ local nidstr="peer_nid: ${nid},"
+ local count
+
+ lfs df -h
+ do_facet $SINGLEMDS $LCTL get_param -n \
+ mdt.*-MDT0000.gss.srpc_serverctx | grep "$nidstr"
+ count=$(do_facet $SINGLEMDS $LCTL get_param -n \
+ mdt.*-MDT0000.gss.srpc_serverctx | grep "$nidstr" |
+ grep -c 'delta: -')
+ echo "found $count expired reverse contexts (1)"
+ # We can have up to 3 expired contexts in the normal case:
+ # - the newest one, that is just about to be renewed
+ # - the previous one that had expired
+ # - the one currently referenced in the sec, not updated in the absence
+ # of client activity.
+ (( count < 4 )) || error "expired reverse contexts should be <= 3 (1)"
+
+ # unmount to get rid of old context
+ umount_client $MOUNT || error "umount $MOUNT failed"
+ kdestroy
+ stack_trap "mount_client $MOUNT ${MOUNT_OPTS} || true" EXIT
+ if is_mounted $MOUNT2; then
+ umount_client $MOUNT2 || error "umount $MOUNT2 failed"
+ stack_trap "mount_client $MOUNT2 ${MOUNT_OPTS}" EXIT
+ fi
+
+ # update ticket lifetime to be 45s
+ stack_trap "/usr/bin/cp -f /etc/krb5.conf.bkp /etc/krb5.conf" EXIT
+ sed -i.bkp s+[^#]ticket_lifetime.*+ticket_lifetime\ =\ 45s+ \
+ /etc/krb5.conf
+ # establish new context, and wait 3x lifetime
+ mount_client $MOUNT ${MOUNT_OPTS} || error "remount failed"
+ lfs df -h
+ sleep 135
+ # re-activate connections, and look for reverse contexts on server side
+ lfs df -h
+ do_facet $SINGLEMDS $LCTL get_param -n \
+ mdt.*-MDT0000.gss.srpc_serverctx | grep "$nidstr"
+ count=$(do_facet $SINGLEMDS $LCTL get_param -n \
+ mdt.*-MDT0000.gss.srpc_serverctx | grep "$nidstr" |
+ grep -c 'delta: -')
+ echo "found $count expired reverse contexts (2)"
+ (( count < 4 )) || error "expired reverse contexts should be <= 3 (2)"
+}
+run_test 200 "check expired reverse gss contexts"
+
complete_test $SECONDS
set_flavor_all null
cleanup_gss