1# See the file LICENSE for redistribution information.
2#
3# Copyright (c) 1999,2008 Oracle.  All rights reserved.
4#
5# $Id: sec002.tcl,v 12.6 2008/01/08 20:58:53 bostic Exp $
6#
7# TEST	sec002
8# TEST	Test of security interface and catching errors in the
9# TEST  face of attackers overwriting parts of existing files.
10proc sec002 { } {
11	global errorInfo
12	global errorCode
13	global has_crypto
14
15	source ./include.tcl
16
17	# Skip test if release does not support encryption.
18	if { $has_crypto == 0 } {
19		puts "Skipping test sec002 for non-crypto release."
20		return
21	}
22
23	set testfile1 $testdir/sec002-1.db
24	set testfile2 $testdir/sec002-2.db
25	set testfile3 $testdir/sec002-3.db
26	set testfile4 $testdir/sec002-4.db
27
28	puts "Sec002: Test of basic encryption interface."
29	env_cleanup $testdir
30
31	set passwd1 "passwd1"
32	set passwd2 "passwd2"
33	set key "key"
34	set data "data"
35	set pagesize 1024
36
37	#
38	# Set up 4 databases, two encrypted, but with different passwords
39	# and one unencrypt, but with checksumming turned on and one
40	# unencrypted and no checksumming.  Place the exact same data
41	# in each one.
42	#
43	puts "\tSec002.a: Setup databases"
44	set db_cmd "-create -pagesize $pagesize -btree "
45	set db [eval {berkdb_open} -encryptaes $passwd1 $db_cmd $testfile1]
46	error_check_good db [is_valid_db $db] TRUE
47	error_check_good dbput [$db put $key $data] 0
48	error_check_good dbclose [$db close] 0
49
50	set db [eval {berkdb_open} -encryptaes $passwd2 $db_cmd $testfile2]
51	error_check_good db [is_valid_db $db] TRUE
52	error_check_good dbput [$db put $key $data] 0
53	error_check_good dbclose [$db close] 0
54
55	set db [eval {berkdb_open} -chksum $db_cmd $testfile3]
56	error_check_good db [is_valid_db $db] TRUE
57	error_check_good dbput [$db put $key $data] 0
58	error_check_good dbclose [$db close] 0
59
60	set db [eval {berkdb_open} $db_cmd $testfile4]
61	error_check_good db [is_valid_db $db] TRUE
62	error_check_good dbput [$db put $key $data] 0
63	error_check_good dbclose [$db close] 0
64
65	#
66	# If we reopen the normal file with the -chksum flag, there
67	# should be no error and checksumming should be ignored.
68	# If we reopen a checksummed file without the -chksum flag,
69	# checksumming should still be in effect.  [#6959]
70	#
71	puts "\tSec002.b: Inheritance of chksum properties"
72	puts "\t\tSec002.b1: Reopen ordinary file with -chksum flag"
73	set db [eval {berkdb_open} -chksum $testfile4]
74	error_check_good open_with_chksum [is_valid_db $db] TRUE
75	set retdata [$db get $key]
76	error_check_good testfile4_get [lindex [lindex $retdata 0] 1] $data
77	error_check_good dbclose [$db close] 0
78
79	puts "\t\tSec002.b2: Reopen checksummed file without -chksum flag"
80	set db [eval {berkdb_open} $testfile3]
81	error_check_good open_wo_chksum [is_valid_db $db] TRUE
82	set retdata [$db get $key]
83	error_check_good testfile3_get [lindex [lindex $retdata 0] 1] $data
84	error_check_good dbclose [$db close] 0
85
86	#
87	# First just touch some bits in the file.  We know that in btree
88	# meta pages, bytes 92-459 are unused.  Scribble on them in both
89	# an encrypted, and both unencrypted files.  We should get
90	# a checksum error for the encrypted, and checksummed files.
91	# We should get no error for the normal file.
92	#
93	set fidlist {}
94	set fid [open $testfile1 r+]
95	lappend fidlist $fid
96	set fid [open $testfile3 r+]
97	lappend fidlist $fid
98	set fid [open $testfile4 r+]
99	lappend fidlist $fid
100
101	puts "\tSec002.c: Overwrite unused space in meta-page"
102	foreach f $fidlist {
103		fconfigure $f -translation binary
104		seek $f 100 start
105		set byte [read $f 1]
106		binary scan $byte c val
107		set newval [expr ~$val]
108		set newbyte [binary format c $newval]
109		seek $f 100 start
110		puts -nonewline $f $newbyte
111		close $f
112	}
113	puts "\tSec002.d: Reopen modified databases"
114	set stat [catch {berkdb_open_noerr -encryptaes $passwd1 $testfile1} ret]
115	error_check_good db:$testfile1 $stat 1
116	error_check_good db:$testfile1:fail \
117	    [is_substr $ret "metadata page checksum error"] 1
118
119	set stat [catch {berkdb_open_noerr -chksum $testfile3} ret]
120	error_check_good db:$testfile3 $stat 1
121	error_check_good db:$testfile3:fail \
122	    [is_substr $ret "metadata page checksum error"] 1
123
124	set stat [catch {berkdb_open_noerr $testfile4} db]
125	error_check_good db:$testfile4 $stat 0
126	error_check_good dbclose [$db close] 0
127
128	# Skip the remainder of the test for Windows platforms.
129	# Forcing the error which causes DB_RUNRECOVERY to be
130	# returned ends up leaving open files that cannot be removed.
131	if { $is_windows_test == 1 } {
132		cleanup $testdir NULL 1
133		puts "Skipping remainder of test for Windows"
134		return
135	}
136
137	puts "\tSec002.e: Replace root page in encrypted w/ encrypted"
138	set fid1 [open $testfile1 r+]
139	fconfigure $fid1 -translation binary
140	set fid2 [open $testfile2 r+]
141	fconfigure $fid2 -translation binary
142	seek $fid1 $pagesize start
143	seek $fid2 $pagesize start
144	fcopy $fid1 $fid2 -size $pagesize
145	close $fid1
146	close $fid2
147
148	set db [berkdb_open_noerr -encryptaes $passwd2 $testfile2]
149	error_check_good db [is_valid_db $db] TRUE
150	set stat [catch {$db get $key} ret]
151	error_check_good dbget $stat 1
152	error_check_good db:$testfile2:fail1 \
153	    [is_substr $ret "checksum error"] 1
154	set stat [catch {$db close} ret]
155	error_check_good dbclose $stat 1
156	error_check_good db:$testfile2:fail2 [is_substr $ret "DB_RUNRECOVERY"] 1
157
158	puts "\tSec002.f: Replace root page in encrypted w/ unencrypted"
159	set fid2 [open $testfile2 r+]
160	fconfigure $fid2 -translation binary
161	set fid4 [open $testfile4 r+]
162	fconfigure $fid4 -translation binary
163	seek $fid2 $pagesize start
164	seek $fid4 $pagesize start
165	fcopy $fid4 $fid2 -size $pagesize
166	close $fid4
167	close $fid2
168
169	set db [berkdb_open_noerr -encryptaes $passwd2 $testfile2]
170	error_check_good db [is_valid_db $db] TRUE
171	set stat [catch {$db get $key} ret]
172	error_check_good dbget $stat 1
173	error_check_good db:$testfile2:fail \
174	    [is_substr $ret "checksum error"] 1
175	set stat [catch {$db close} ret]
176	error_check_good dbclose $stat 1
177	error_check_good db:$testfile2:fail [is_substr $ret "DB_RUNRECOVERY"] 1
178
179	cleanup $testdir NULL 1
180}
181