forked from rapid7/metasploit-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmsfupdate
executable file
·164 lines (139 loc) · 5.11 KB
/
msfupdate
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
#!/usr/bin/env ruby
# -*- coding: binary -*-
# $Id$
# $Revision$
msfbase = __FILE__
while File.symlink?(msfbase)
msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
end
@msfbase_dir = File.dirname(msfbase)
@args = ARGV.dup
# May be changed
@configdir = File.expand_path(File.join(File.dirname(msfbase), "data", "svn"))
Dir.chdir(@msfbase_dir)
$stderr.puts "[*]"
$stderr.puts "[*] Attempting to update the Metasploit Framework..."
$stderr.puts "[*]"
$stderr.puts ""
if not (Process.uid == 0 or File.stat(msfbase).owned?)
$stderr.puts "[-] ERROR: User running msfupdate does not own the metasploit install"
$stderr.puts "Please run msfupdate as the same user who installed metasploit."
end
def is_pro
File.exists?(File.expand_path(File.join(@msfbase_dir, "..", "engine", "update.rb")))
end
def is_git
File.directory?(File.join(@msfbase_dir, ".git"))
end
def is_svn
File.directory?(File.join(@msfbase_dir, ".svn"))
end
# Adding an upstream enables msfupdate to pull updates from
# Rapid7's metasploit-framework repo instead of the repo
# the user originally cloned or forked.
def add_git_upstream
$stdout.puts "[*] Attempting to add remote 'upstream' to your local git repository."
system("git", "remote", "add", "upstream", "git://github.com/rapid7/metasploit-framework.git")
$stdout.puts "[*] Added remote 'upstream' to your local git repository."
end
def print_deprecation_warning
$stdout.puts "[*] Deprecation Note: The next version of Metasploit will"
$stdout.puts "[*] update over the git protocol, which requires outbound"
$stdout.puts "[*] access to github.com:9418/TCP."
$stdout.puts "[*] Please adjust your egress firewall rules accordingly."
end
# Some of these args are meaningful for SVN, some for Git,
# some for both. Fun times.
@args.each_with_index do |arg,i|
case arg
# Handle the old wait/nowait argument behavior
when "wait", "nowait"
@wait_index = i
@actually_wait = (arg == "wait")
# An empty or absent config-dir means a default config-dir
when "--config-dir"
@configdir_index = i
# A defined config dir means a defined config-dir
when /--config-dir=(.*)?/
# Spaces in the directory should be fine since this whole thing is passed
# as a single argument via the multi-arg syntax for system() below.
@configdir = $1
@configdir_index = i
when /--git-remote=([^\s]*)?/
@git_remote = $1
@git_remote_index = i
when /--git-branch=([^\s]*)?/
@git_branch = $1
@git_branch_index = i
end
end
@args[@wait_index] = nil if @wait_index
@args[@configdir_index] = nil if @configdir_index
@args[@git_remote_index] = nil if @git_remote_index
@args[@git_branch_index] = nil if @git_branch_index
@args = @args.compact
####### Since we're SVN, do it all this way #######
if is_svn
print_deprecation_warning
@args.push("--config-dir=#{@configdir}")
@args.push("--non-interactive")
res = system("svn", "cleanup")
if res.nil?
$stderr.puts "[-] ERROR: Failed to run svn"
$stderr.puts ""
$stderr.puts "[-] If you used a binary installer, make sure you run the symlink in"
$stderr.puts "[-] /usr/local/bin instead of running this file directly (e.g.: ./msfupdate)"
$stderr.puts "[-] to ensure a proper environment."
exit 1
else
# Cleanup worked, go ahead and update
system("svn", "update", *@args)
end
end
####### Since we're Git, do it all that way #######
if is_git
out = `git remote show upstream` # Actually need the output for this one.
add_git_upstream unless $?.success? and out =~ %r{(https|git|git@github\.com):(//github\.com/)?(rapid7/metasploit-framework\.git)}
remote = @git_remote || "upstream"
branch = @git_branch || "master"
# This will save local changes in a stash, but won't
# attempt to reapply them. If the user wants them back
# they can always git stash pop them, and that presumes
# they know what they're doing when they're editing local
# checkout, which presumes they're not using msfupdate
# to begin with.
#
# Note, this requires at least user.name and user.email
# to be configured in the global git config. Installers should
# take care that this is done. TODO: Enforce this in msfupdate
committed = system("git", "diff", "--quiet", "HEAD")
if committed.nil?
$stderr.puts "[-] ERROR: Failed to run git"
$stderr.puts ""
$stderr.puts "[-] If you used a binary installer, make sure you run the symlink in"
$stderr.puts "[-] /usr/local/bin instead of running this file directly (e.g.: ./msfupdate)"
$stderr.puts "[-] to ensure a proper environment."
exit 1
elsif not committed
system("git", "stash")
$stdout.puts "[*] Stashed local changes to avoid merge conflicts."
$stdout.puts "[*] Run `git stash pop` to reapply local changes."
end
system("git", "reset", "HEAD", "--hard")
system("git", "checkout", branch)
system("git", "fetch", remote)
system("git", "merge", "#{remote}/#{branch}")
end
if is_pro
update_script = File.expand_path(File.join(@msfbase_dir, "..", "engine", "update.rb"))
system("ruby", update_script)
end
unless is_svn || is_git || is_pro
raise RuntimeError, "Cannot determine checkout type: `#{@msfbase_dir}'"
end
if @actually_wait
$stderr.puts ""
$stderr.puts "[*] Please hit enter to exit"
$stderr.puts ""
$stdin.readline
end