mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-16 21:29:59 +01:00
test generators: unify checksum check functions
This commit is contained in:
@@ -29,10 +29,9 @@ function generate()
|
|||||||
function check()
|
function check()
|
||||||
{
|
{
|
||||||
lib_hdr1_killed || exit 2
|
lib_hdr1_killed || exit 2
|
||||||
|
lib_hdr0_checksum || exit 2
|
||||||
|
|
||||||
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
||||||
chks_res0=$(read_sha256_checksum $TGT_IMG)
|
|
||||||
test "$chks0" = "$chks_res0" || exit 2
|
|
||||||
new_obj_len=$(jq -c -M '.keyslots."1".kdf | length' $TMPDIR/json_res0)
|
new_obj_len=$(jq -c -M '.keyslots."1".kdf | length' $TMPDIR/json_res0)
|
||||||
test $((obj_len+2)) -eq $new_obj_len || exit 2
|
test $((obj_len+2)) -eq $new_obj_len || exit 2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,10 +44,9 @@ function generate()
|
|||||||
function check()
|
function check()
|
||||||
{
|
{
|
||||||
lib_hdr1_killed || exit 2
|
lib_hdr1_killed || exit 2
|
||||||
|
lib_hdr0_checksum || exit 2
|
||||||
|
|
||||||
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
||||||
chks_res0=$(read_sha256_checksum $TGT_IMG)
|
|
||||||
test "$chks0" = "$chks_res0" || exit 2
|
|
||||||
#json_str_res0=$(< $TMPDIR/json_res0)
|
#json_str_res0=$(< $TMPDIR/json_res0)
|
||||||
read -r json_str_res0 < $TMPDIR/json_res0
|
read -r json_str_res0 < $TMPDIR/json_res0
|
||||||
test ${#json_str_res0} -eq $((LUKS2_JSON_SIZE*512-1)) || exit 2
|
test ${#json_str_res0} -eq $((LUKS2_JSON_SIZE*512-1)) || exit 2
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ function generate()
|
|||||||
|
|
||||||
function check()
|
function check()
|
||||||
{
|
{
|
||||||
chks_res0=$(read_sha256_checksum $TGT_IMG)
|
lib_hdr0_checksum || exit 2
|
||||||
test "$chks0" = "$chks_res0" || exit 2
|
|
||||||
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
||||||
read -r json_str_res0 < $TMPDIR/json_res0
|
read -r json_str_res0 < $TMPDIR/json_res0
|
||||||
test ${#json_str_res0} -eq $((LUKS2_JSON_SIZE*512)) || exit 2
|
test ${#json_str_res0} -eq $((LUKS2_JSON_SIZE*512)) || exit 2
|
||||||
|
|||||||
@@ -29,9 +29,8 @@ function generate()
|
|||||||
|
|
||||||
function check()
|
function check()
|
||||||
{
|
{
|
||||||
read_luks2_bin_hdr1 $TGT_IMG $TMPDIR/hdr_res1
|
lib_hdr1_checksum || exit 2
|
||||||
chks_res1=$(read_sha256_checksum $TMPDIR/hdr_res1)
|
|
||||||
test "$chks1" = "$chks_res1" || exit 2
|
|
||||||
read_luks2_json1 $TGT_IMG $TMPDIR/json_res1
|
read_luks2_json1 $TGT_IMG $TMPDIR/json_res1
|
||||||
read -r json_str_res1 < $TMPDIR/json_res1
|
read -r json_str_res1 < $TMPDIR/json_res1
|
||||||
test ${#json_str_res1} -eq $((LUKS2_JSON_SIZE*512)) || exit 2
|
test ${#json_str_res1} -eq $((LUKS2_JSON_SIZE*512)) || exit 2
|
||||||
|
|||||||
@@ -13,19 +13,17 @@
|
|||||||
|
|
||||||
function generate()
|
function generate()
|
||||||
{
|
{
|
||||||
chks0=$(echo "Arbitrary chosen string: D'oh!" | calc_sha256_checksum_stdin)
|
CHKS0=$(echo "Arbitrary chosen string: D'oh!" | calc_sha256_checksum_stdin)
|
||||||
chks1=$(echo "D'oh!: arbitrary chosen string" | calc_sha256_checksum_stdin)
|
CHKS1=$(echo "D'oh!: arbitrary chosen string" | calc_sha256_checksum_stdin)
|
||||||
write_checksum $chks0 $TGT_IMG
|
write_checksum $CHKS0 $TGT_IMG
|
||||||
write_checksum $chks1 $TMPDIR/hdr1
|
write_checksum $CHKS1 $TMPDIR/hdr1
|
||||||
write_luks2_bin_hdr1 $TMPDIR/hdr1 $TGT_IMG
|
write_luks2_bin_hdr1 $TMPDIR/hdr1 $TGT_IMG
|
||||||
}
|
}
|
||||||
|
|
||||||
function check()
|
function check()
|
||||||
{
|
{
|
||||||
chks_res0=$(read_sha256_checksum $TGT_IMG)
|
lib_hdr0_checksum || exit 2
|
||||||
chks_res1=$(read_sha256_checksum $TMPDIR/hdr1)
|
lib_hdr1_checksum || exit 2
|
||||||
test "$chks0" = "$chks_res0" || exit 2
|
|
||||||
test "$chks1" = "$chks_res1" || exit 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lib_prepare $@
|
lib_prepare $@
|
||||||
|
|||||||
@@ -13,14 +13,13 @@
|
|||||||
|
|
||||||
function generate()
|
function generate()
|
||||||
{
|
{
|
||||||
chks=$(echo "Arbitrary chosen string: D'oh!" | calc_sha256_checksum_stdin)
|
CHKS0=$(echo "Arbitrary chosen string: D'oh!" | calc_sha256_checksum_stdin)
|
||||||
write_checksum $chks $TGT_IMG
|
write_checksum $CHKS0 $TGT_IMG
|
||||||
}
|
}
|
||||||
|
|
||||||
function check()
|
function check()
|
||||||
{
|
{
|
||||||
chks_res=$(read_sha256_checksum $TGT_IMG)
|
lib_hdr0_checksum || exit 2
|
||||||
test "$chks" = "$chks_res" || exit 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lib_prepare $@
|
lib_prepare $@
|
||||||
|
|||||||
@@ -13,15 +13,14 @@
|
|||||||
|
|
||||||
function generate()
|
function generate()
|
||||||
{
|
{
|
||||||
chks=$(echo "Arbitrary chosen string: D'oh!" | calc_sha256_checksum_stdin)
|
CHKS1=$(echo "Arbitrary chosen string: D'oh!" | calc_sha256_checksum_stdin)
|
||||||
write_checksum $chks $TMPDIR/hdr1
|
write_checksum $CHKS1 $TMPDIR/hdr1
|
||||||
write_luks2_bin_hdr1 $TMPDIR/hdr1 $TGT_IMG
|
write_luks2_bin_hdr1 $TMPDIR/hdr1 $TGT_IMG
|
||||||
}
|
}
|
||||||
|
|
||||||
function check()
|
function check()
|
||||||
{
|
{
|
||||||
chks_res=$(read_sha256_checksum $TMPDIR/hdr1)
|
lib_hdr1_checksum || exit 2
|
||||||
test "$chks" = "$chks_res" || exit 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lib_prepare $@
|
lib_prepare $@
|
||||||
|
|||||||
@@ -28,10 +28,9 @@ function generate()
|
|||||||
function check()
|
function check()
|
||||||
{
|
{
|
||||||
lib_hdr1_killed || exit 2
|
lib_hdr1_killed || exit 2
|
||||||
|
lib_hdr0_checksum || exit 2
|
||||||
|
|
||||||
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
||||||
chks_res0=$(read_sha256_checksum $TGT_IMG)
|
|
||||||
test "$chks0" = "$chks_res0" || exit 2
|
|
||||||
read -r json_str_res0 < $TMPDIR/json_res0
|
read -r json_str_res0 < $TMPDIR/json_res0
|
||||||
test "$json_str" = "$json_str_res0" || exit 2
|
test "$json_str" = "$json_str_res0" || exit 2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,10 +28,9 @@ function generate()
|
|||||||
function check()
|
function check()
|
||||||
{
|
{
|
||||||
lib_hdr1_killed || exit 2
|
lib_hdr1_killed || exit 2
|
||||||
|
lib_hdr0_checksum || exit 2
|
||||||
|
|
||||||
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
||||||
chks_res0=$(read_sha256_checksum $TGT_IMG)
|
|
||||||
test "$chks0" = "$chks_res0" || exit 2
|
|
||||||
IFS= read -r json_str_res0 < $TMPDIR/json_res0
|
IFS= read -r json_str_res0 < $TMPDIR/json_res0
|
||||||
test "$json_str" = "$json_str_res0" || exit 2
|
test "$json_str" = "$json_str_res0" || exit 2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,10 +30,9 @@ function generate()
|
|||||||
function check()
|
function check()
|
||||||
{
|
{
|
||||||
lib_hdr1_killed || exit 2
|
lib_hdr1_killed || exit 2
|
||||||
|
lib_hdr0_checksum || exit 2
|
||||||
|
|
||||||
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
||||||
chks_res0=$(read_sha256_checksum $TGT_IMG)
|
|
||||||
test "$chks0" = "$chks_res0" || exit 2
|
|
||||||
new_arr_len=$(jq -c -M '.digests."0".keyslots | length' $TMPDIR/json_res0)
|
new_arr_len=$(jq -c -M '.digests."0".keyslots | length' $TMPDIR/json_res0)
|
||||||
test $((arr_len-1)) -eq $new_arr_len || exit 2
|
test $((arr_len-1)) -eq $new_arr_len || exit 2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,10 +28,9 @@ function generate()
|
|||||||
function check()
|
function check()
|
||||||
{
|
{
|
||||||
lib_hdr1_killed || exit 2
|
lib_hdr1_killed || exit 2
|
||||||
|
lib_hdr0_checksum || exit 2
|
||||||
|
|
||||||
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
||||||
chks_res0=$(read_sha256_checksum $TGT_IMG)
|
|
||||||
test "$chks0" = "$chks_res0" || exit 2
|
|
||||||
new_arr_len=$(jq -c -M '.digests."1".keyslots | length' $TMPDIR/json_res0)
|
new_arr_len=$(jq -c -M '.digests."1".keyslots | length' $TMPDIR/json_res0)
|
||||||
test 1 -eq $new_arr_len || exit 2
|
test 1 -eq $new_arr_len || exit 2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,10 +32,9 @@ function generate()
|
|||||||
function check()
|
function check()
|
||||||
{
|
{
|
||||||
lib_hdr1_killed || exit 2
|
lib_hdr1_killed || exit 2
|
||||||
|
lib_hdr0_checksum || exit 2
|
||||||
|
|
||||||
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
||||||
chks_res0=$(read_sha256_checksum $TGT_IMG)
|
|
||||||
test "$chks0" = "$chks_res0" || exit 2
|
|
||||||
new_arr_len=$(jq -c -M '.digests."0".keyslots | length' $TMPDIR/json_res0)
|
new_arr_len=$(jq -c -M '.digests."0".keyslots | length' $TMPDIR/json_res0)
|
||||||
test $((arr_len+1)) -eq $new_arr_len || exit 2
|
test $((arr_len+1)) -eq $new_arr_len || exit 2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,10 +30,9 @@ function generate()
|
|||||||
function check()
|
function check()
|
||||||
{
|
{
|
||||||
lib_hdr1_killed || exit 2
|
lib_hdr1_killed || exit 2
|
||||||
|
lib_hdr0_checksum || exit 2
|
||||||
|
|
||||||
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
||||||
chks_res0=$(read_sha256_checksum $TGT_IMG)
|
|
||||||
test "$chks0" = "$chks_res0" || exit 2
|
|
||||||
new_arr_len=$(jq -c -M '.tokens."0".keyslots | length' $TMPDIR/json_res0)
|
new_arr_len=$(jq -c -M '.tokens."0".keyslots | length' $TMPDIR/json_res0)
|
||||||
test $new_arr_len -eq 2 || exit 2
|
test $new_arr_len -eq 2 || exit 2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,10 +32,9 @@ function generate()
|
|||||||
function check()
|
function check()
|
||||||
{
|
{
|
||||||
lib_hdr1_killed || exit 2
|
lib_hdr1_killed || exit 2
|
||||||
|
lib_hdr0_checksum || exit 2
|
||||||
|
|
||||||
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
||||||
chks_res0=$(read_sha256_checksum $TGT_IMG)
|
|
||||||
test "$chks0" = "$chks_res0" || exit 2
|
|
||||||
new_arr_len=$(jq -c -M '.digests."0".segments | length' $TMPDIR/json_res0)
|
new_arr_len=$(jq -c -M '.digests."0".segments | length' $TMPDIR/json_res0)
|
||||||
test $((arr_len+1)) -eq $new_arr_len || exit 2
|
test $((arr_len+1)) -eq $new_arr_len || exit 2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,10 +47,9 @@ function generate()
|
|||||||
function check()
|
function check()
|
||||||
{
|
{
|
||||||
lib_hdr1_killed || exit 2
|
lib_hdr1_killed || exit 2
|
||||||
|
lib_hdr0_checksum || exit 2
|
||||||
|
|
||||||
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
||||||
chks_res0=$(read_sha256_checksum $TGT_IMG)
|
|
||||||
test "$chks0" = "$chks_res0" || exit 2
|
|
||||||
read -r json_str_res0 < $TMPDIR/json_res0
|
read -r json_str_res0 < $TMPDIR/json_res0
|
||||||
test ${#json_str_res0} -eq $((LUKS2_JSON_SIZE*512)) || exit 2
|
test ${#json_str_res0} -eq $((LUKS2_JSON_SIZE*512)) || exit 2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,10 +28,9 @@ function generate()
|
|||||||
function check()
|
function check()
|
||||||
{
|
{
|
||||||
lib_hdr1_killed || exit 2
|
lib_hdr1_killed || exit 2
|
||||||
|
lib_hdr0_checksum || exit 2
|
||||||
|
|
||||||
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
||||||
chks_res0=$(read_sha256_checksum $TGT_IMG)
|
|
||||||
test "$chks0" = "$chks_res0" || exit 2
|
|
||||||
read -r json_str_res0 < $TMPDIR/json_res0
|
read -r json_str_res0 < $TMPDIR/json_res0
|
||||||
local len=${#json_str_res0}
|
local len=${#json_str_res0}
|
||||||
len=$((len-1))
|
len=$((len-1))
|
||||||
|
|||||||
@@ -32,10 +32,9 @@ function generate()
|
|||||||
function check()
|
function check()
|
||||||
{
|
{
|
||||||
lib_hdr1_killed || exit 2
|
lib_hdr1_killed || exit 2
|
||||||
|
lib_hdr0_checksum || exit 2
|
||||||
|
|
||||||
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
||||||
chks_res0=$(read_sha256_checksum $TGT_IMG)
|
|
||||||
test "$chks0" = "$chks_res0" || exit 2
|
|
||||||
|
|
||||||
_dd if=$TMPDIR/json_res0 of=$TMPDIR/quote skip=$((json_len_orig+SPACE)) count=${#QUOTE} bs=1
|
_dd if=$TMPDIR/json_res0 of=$TMPDIR/quote skip=$((json_len_orig+SPACE)) count=${#QUOTE} bs=1
|
||||||
json_str_res0=$(head -c ${#QUOTE} $TMPDIR/quote)
|
json_str_res0=$(head -c ${#QUOTE} $TMPDIR/quote)
|
||||||
|
|||||||
@@ -29,10 +29,9 @@ function generate()
|
|||||||
function check()
|
function check()
|
||||||
{
|
{
|
||||||
lib_hdr1_killed || exit 2
|
lib_hdr1_killed || exit 2
|
||||||
|
lib_hdr0_checksum || exit 2
|
||||||
|
|
||||||
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
||||||
chks_res0=$(read_sha256_checksum $TGT_IMG)
|
|
||||||
test "$chks0" = "$chks_res0" || exit 2
|
|
||||||
new_obj_len=$(jq -c -M '.keyslots."2".kdf | length' $TMPDIR/json_res0)
|
new_obj_len=$(jq -c -M '.keyslots."2".kdf | length' $TMPDIR/json_res0)
|
||||||
test $((obj_len+2)) -eq $new_obj_len || exit 2
|
test $((obj_len+2)) -eq $new_obj_len || exit 2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,10 +29,9 @@ function generate()
|
|||||||
function check()
|
function check()
|
||||||
{
|
{
|
||||||
lib_hdr1_killed || exit 2
|
lib_hdr1_killed || exit 2
|
||||||
|
lib_hdr0_checksum || exit 2
|
||||||
|
|
||||||
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
read_luks2_json0 $TGT_IMG $TMPDIR/json_res0
|
||||||
chks_res0=$(read_sha256_checksum $TGT_IMG)
|
|
||||||
test "$chks0" = "$chks_res0" || exit 2
|
|
||||||
new_obj_len=$(jq -c -M '.keyslots."2".kdf | length' $TMPDIR/json_res0)
|
new_obj_len=$(jq -c -M '.keyslots."2".kdf | length' $TMPDIR/json_res0)
|
||||||
test $((obj_len+2)) -eq $new_obj_len || exit 2
|
test $((obj_len+2)) -eq $new_obj_len || exit 2
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,6 +197,10 @@ function lib_prepare()
|
|||||||
TGT_IMG=$1/$(test_img_name $0)
|
TGT_IMG=$1/$(test_img_name $0)
|
||||||
SRC_IMG=$2
|
SRC_IMG=$2
|
||||||
|
|
||||||
|
# wipe checksums
|
||||||
|
CHKS0=0
|
||||||
|
CHKS1=0
|
||||||
|
|
||||||
cp $SRC_IMG $TGT_IMG
|
cp $SRC_IMG $TGT_IMG
|
||||||
test -d $TMPDIR || mkdir $TMPDIR
|
test -d $TMPDIR || mkdir $TMPDIR
|
||||||
read_luks2_json0 $TGT_IMG $TMPDIR/json0
|
read_luks2_json0 $TGT_IMG $TMPDIR/json0
|
||||||
@@ -219,8 +223,8 @@ function lib_mangle_json_hdr0()
|
|||||||
|
|
||||||
merge_bin_hdr_with_json $TMPDIR/hdr0 $TMPDIR/json0 $TMPDIR/area0 $jsn_sz
|
merge_bin_hdr_with_json $TMPDIR/hdr0 $TMPDIR/json0 $TMPDIR/area0 $jsn_sz
|
||||||
erase_checksum $TMPDIR/area0
|
erase_checksum $TMPDIR/area0
|
||||||
chks0=$(calc_sha256_checksum_file $TMPDIR/area0)
|
CHKS0=$(calc_sha256_checksum_file $TMPDIR/area0)
|
||||||
write_checksum $chks0 $TMPDIR/area0
|
write_checksum $CHKS0 $TMPDIR/area0
|
||||||
test -n "$kill_hdr" && kill_bin_hdr $TMPDIR/area0
|
test -n "$kill_hdr" && kill_bin_hdr $TMPDIR/area0
|
||||||
write_luks2_hdr0 $TMPDIR/area0 $TGT_IMG $mda_sz
|
write_luks2_hdr0 $TMPDIR/area0 $TGT_IMG $mda_sz
|
||||||
}
|
}
|
||||||
@@ -233,8 +237,8 @@ function lib_mangle_json_hdr1()
|
|||||||
|
|
||||||
merge_bin_hdr_with_json $TMPDIR/hdr1 $TMPDIR/json1 $TMPDIR/area1 $jsn_sz
|
merge_bin_hdr_with_json $TMPDIR/hdr1 $TMPDIR/json1 $TMPDIR/area1 $jsn_sz
|
||||||
erase_checksum $TMPDIR/area1
|
erase_checksum $TMPDIR/area1
|
||||||
chks1=$(calc_sha256_checksum_file $TMPDIR/area1)
|
CHKS1=$(calc_sha256_checksum_file $TMPDIR/area1)
|
||||||
write_checksum $chks1 $TMPDIR/area1
|
write_checksum $CHKS1 $TMPDIR/area1
|
||||||
test -n "$kill_hdr" && kill_bin_hdr $TMPDIR/area1
|
test -n "$kill_hdr" && kill_bin_hdr $TMPDIR/area1
|
||||||
write_luks2_hdr1 $TMPDIR/area1 $TGT_IMG $mda_sz
|
write_luks2_hdr1 $TMPDIR/area1 $TGT_IMG $mda_sz
|
||||||
}
|
}
|
||||||
@@ -264,3 +268,16 @@ function lib_hdr1_killed()
|
|||||||
local str_res1=$(head -c 6 $TMPDIR/hdr_res1)
|
local str_res1=$(head -c 6 $TMPDIR/hdr_res1)
|
||||||
test "$str_res1" = "VACUUM"
|
test "$str_res1" = "VACUUM"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function lib_hdr0_checksum()
|
||||||
|
{
|
||||||
|
local chks_res0=$(read_sha256_checksum $TGT_IMG)
|
||||||
|
test "$CHKS0" = "$chks_res0"
|
||||||
|
}
|
||||||
|
|
||||||
|
function lib_hdr1_checksum()
|
||||||
|
{
|
||||||
|
read_luks2_bin_hdr1 $TGT_IMG $TMPDIR/hdr_res1
|
||||||
|
local chks_res1=$(read_sha256_checksum $TMPDIR/hdr_res1)
|
||||||
|
test "$CHKS1" = "$chks_res1"
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user