-
Notifications
You must be signed in to change notification settings - Fork 0
/
wipeout.rb
executable file
·190 lines (156 loc) · 4.14 KB
/
wipeout.rb
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
#!/usr/bin/ruby
#
# Wipeout - Fast, secure, interactive disk erase utility
#
# Latest version here: https://github.com/courtney-rosenthal/wipeout
#
# Pattern that will match the device once it's connected to the system.
PATTERN_DEV = "/dev/sd?"
# After the wipe is performed, check this amount at the beginning of the
# disk to ensure it's all zeroes, to confirm a successful wipe.
WIPE_CHECK_MB = 500
#
# main - main program
#
def main
if `id -u`.rstrip != "0"
raise "This must be run as the root user."
end
dev = acquireDevice
puts "Detected device = #{dev}"
verifySecureWipeCapable(dev)
confirmForWipe(dev)
performWipe(dev)
verifyWipe(dev)
end
#
# acquireDevice - wait for a device to be connected, returns path of the device
#
def acquireDevice
devicesBefore = Dir.glob(PATTERN_DEV)
print "Searching ... connect drive now .."
loop do
print "."
sleep 1
devicesAdded = Dir.glob(PATTERN_DEV) - devicesBefore
case devicesAdded.length
when 0
# nothing added yet
when 1
puts " done!"
return devicesAdded.first
else
raise "I'm confused -- I see multiple devices added!"
end
end
end
#
# getHdParamInfo - get info from a device with the "hdparam" command
#
# Returns a list of lines output by the command, with spaces collapsed and trimmed.
#
def getHdParamInfo(dev)
output = `hdparm -I #{dev}`
if $?.exitstatus != 0
raise "Failed to run hdparm."
end
lines = output.split("\n") \
.map { |s| s.gsub(/[ \t]+/, " ") } \
.map { |s| s.strip }
if lines.empty?
raise "Failed to retrieve output from hdparm command."
end
return lines
end
#
# verifySecureWipeCapable - verify device supports ATA Secure Erase
#
# Also displays some device information.
#
def verifySecureWipeCapable(dev)
lines = getHdParamInfo(dev)
if lines.include?("frozen")
raise "Cannot wipe: device has been frozen."
end
if ! lines.include?("not frozen")
raise "Cannot wipe: cannot verify device frozen state."
end
def lines.getLineFromList(re)
result = self.filter { |s| s =~ re }
if result.length != 1
raise "Cannot determine device information for: #{re}"
end
return result.first
end
puts " " + lines.getLineFromList(/Model Number/)
puts " Estimated erase time: " + lines.getLineFromList(/SECURITY ERASE/).sub(/ .*/, "")
end
#
# confirmWipe - display current partition table then prompt user for yes/no response to start wipe
#
def confirmForWipe(dev)
puts ""
puts "Current partition table:"
system("fdisk -l #{dev} | sed -e 's/^/ /'")
puts ""
puts "THIS DEVICE IS ABOUT TO BE COMPLETELY ERASED !!!"
loop do
print "Proceed to erase #{dev}? (yes/no) : "
case gets.rstrip
when "yes"
return
when "no"
raise "Aborted by request"
else
puts 'Huh? Please answer "yes" or "no".'
end
end
end
#
# performWipe - perform ATA secure erase on a device
#
def performWipe(dev)
# The password doesn't need to be secret. It's only going to live for the duration of the wipe.
pass="secretPassword"
puts ""
runCommand("hdparm --user-master u --security-set-pass #{pass} #{dev}")
lines = getHdParamInfo(dev)
if ! lines.include?("enabled")
raise "Failed to set security password on device."
end
runCommand("hdparm --user-master u --security-erase #{pass} #{dev}")
lines = getHdParamInfo(dev)
if ! lines.include?("not enabled")
raise "Failed to perform secure erase."
end
puts "Wipe command has completed."
end
#
# runCommand - run a command
#
def runCommand(cmd)
puts("+ #{cmd}")
system(cmd)
if $?.exitstatus != 0
raise "Command failed with status: #{$?}"
end
end
#
# verifyWipe - verify that a device has been wiped
#
# Read back the first WIPE_CHECK_MB of the drive and ensure it is all zeroes.
#
def verifyWipe(dev)
puts ""
puts "Confirming wipe was successful ... stand by ~30 seconds ..."
count=`dd if=#{dev} bs=1M count=#{WIPE_CHECK_MB} 2>/dev/null | tr -d '\\0' | wc -c`.rstrip
if count != "0"
raise "WIPE FAILED!! Disk still has data."
end
puts "Wipe is successful!"
end
##############################################################################
#
# begin execution
#
main