GP-4173 Complete transition to using --option params with bsim and bsim_ctl commands

This commit is contained in:
ghidra1 2024-01-03 17:29:45 -05:00
parent 0de3f53c11
commit 735cb1a5c3
12 changed files with 830 additions and 718 deletions

View File

@ -69,7 +69,7 @@ This is equivalent to:
Use a command-line like this to generate and commit signatures from a Ghidra Server
repository to the Elasticsearch database created above:
bsim generatesigs ghidra://1.2.3.4/repo bsim=elastic://1.2.3.4:9200/repo
bsim generatesigs ghidra://1.2.3.4/repo --bsim elastic://1.2.3.4:9200/repo
Within Ghidra's BSim client, enter the same URL into the database connection
panel in order to place queries to your Elasticsearch deployment. See the BSim

View File

@ -39,18 +39,18 @@
<DIV class="informalexample">
<PRE>
<CODE class="computeroutput">
bsim_ctl start &lt;/datadir-path [auth=pki|password|trust] [--noLocalAuth] [cafile=&lt;/cacert-path&gt;] [dn=".."]
bsim_ctl start &lt;/datadir-path&gt; [--auth|-a&nbsp;pki|password|trust] [--noLocalAuth] [--cafile&nbsp;&lt;/cacert-path&gt;] [--dn&nbsp;"&lt;distinguished-name&gt;"]
bsim_ctl stop &lt;/datadir-path&gt; [--force]
bsim_ctl adduser &lt;/datadir-path&gt; &lt;username&gt; [dn=".."]
bsim_ctl adduser &lt;/datadir-path&gt; &lt;username&gt; [--dn&nbsp;"&lt;distinguished-name&gt;"]
bsim_ctl dropuser &lt;/datadir-path&gt; &lt;username&gt;
bsim_ctl resetpassword &lt;username&gt;
bsim_ctl changeauth &lt;/datadir-path&gt; [auth=pki|password|trust] [--noLocalAuth] [cafile=&lt;/cacert-path&gt;] [dn=".."]
bsim_ctl changeauth &lt;/datadir-path&gt; [--auth|-a&nbsp;pki|password|trust] [--noLocalAuth] [--cafile&nbsp;&lt;/cacert-path&gt;] [--dn&nbsp;"&lt;distinguished-name&gt;"]
bsim_ctl changeprivilege &lt;username&gt; admin|user
Global Options:
port=&lt;portnum&gt;
user=&lt;username&gt;
cert=&lt;/certfile-path&gt;
--port|-p&nbsp;&lt;portnum&gt;
--user|-u&nbsp;&lt;username&gt;
--cert&nbsp;&lt;/certfile-path&gt;
</CODE>
</PRE>
</DIV>
@ -59,9 +59,11 @@
starting and stopping a BSim server using the PostgreSQL back-end. The utility cannot be
used with either an Elasticsearch server or a local H2 database.
All commands must be run on the machine hosting the server.
Optional parameters for a given command are indicated by square brackets '[' and ']'.
Options with an '=' character require a user specified value. If the value string requires
space characters, it should be enclosed in double quotes.</P>
Optional parameters for a given command are indicated by square brackets '[' and ']'
and always start with either '-' or '--' characters. If an associated value is required
and contains space characters it should be enclosed in double quotes. Options which require
a value may be separated by a space or a equal "=" character (e.g.,
<SPAN class="command"><STRONG>--auth=password</STRONG></SPAN>).
<DIV class="informalexample">
<DIV class="variablelist">
@ -77,42 +79,42 @@
database with <SPAN class="emphasis"><EM>admin</EM></SPAN> privileges.</P>
<P>During a restart, any authentication options (with the exception of the global
<SPAN class="bold"><STRONG>cert=</STRONG></SPAN> option) are unnecessary and will
<SPAN class="bold"><STRONG>--cert</STRONG></SPAN> option) are unnecessary and will
be ignored. The PostgreSQL server will be restarted with the already established
settings. To actually change the settings, use the <SPAN class=
"bold"><STRONG>changeauth</STRONG></SPAN> command before restarting.</P>
<P><SPAN class="command"><STRONG>auth=</STRONG></SPAN><SPAN class=
"emphasis"><EM>type</EM></SPAN> - specifies the authentication type (<B>pki |
<P><SPAN class="command"><STRONG>--auth|-a&nbsp;</STRONG></SPAN><SPAN class=
"emphasis"><EM>&lt;type&gt;</EM></SPAN> - specifies the authentication type (<B>pki |
password | trust</B>) for a new database: <SPAN class=
"emphasis"><EM>trust</EM></SPAN> for no authentication, <SPAN class=
"emphasis"><EM>password</EM></SPAN> for password authentication, and <SPAN class=
"emphasis"><EM>pki</EM></SPAN> for authentication using public key certificates.
With the <SPAN class="emphasis"><EM>pki</EM></SPAN> setting, both the <SPAN class=
"bold"><STRONG>cafile=</STRONG></SPAN> and the <SPAN class=
"bold"><STRONG>dn=</STRONG></SPAN> options also need to be provided; additionally
the <SPAN class="bold"><STRONG>cert=</STRONG></SPAN> option must be provided unless
"bold"><STRONG>--cafile</STRONG></SPAN> and the <SPAN class=
"bold"><STRONG>--dn</STRONG></SPAN> options also need to be provided; additionally
the <SPAN class="bold"><STRONG>--cert</STRONG></SPAN> option must be provided unless
the <SPAN class="bold"><STRONG>--noLocalAuth</STRONG></SPAN> option is also
given.</P>
<P><SPAN class="command"><STRONG>--noLocalAuth</STRONG></SPAN> - used together with
the <SPAN class="command"><STRONG>auth=</STRONG></SPAN> option causes
the <SPAN class="command"><STRONG>--auth</STRONG></SPAN> option causes
authentication to not be required for local connections, i.e. localhost.</P>
<P><SPAN class="command"><STRONG>cafile=</STRONG></SPAN><SPAN class=
"emphasis"><EM>/cafile-path</EM></SPAN> - specifies an absolute path to a
<P><SPAN class="command"><STRONG>--cafile&nbsp;</STRONG></SPAN><SPAN class=
"emphasis"><EM>&lt;/cafile-path&gt;</EM></SPAN> - specifies an absolute path to a
certificate authority file and is required for <SPAN class=
"command"><STRONG>auth=pki</STRONG></SPAN>. This file should contain the
"command"><STRONG>--auth&nbsp;pki</STRONG></SPAN>. This file should contain the
certificates the PostgreSQL server will use to authenticate in PEM format
concatenated together.</P>
<P><SPAN class="command"><STRONG>dn=</STRONG></SPAN><SPAN class=
"emphasis"><EM>name</EM></SPAN> - specifies the Distinguished Name for the admin
user and is required for <SPAN class=
"command"><STRONG>auth=pki</STRONG></SPAN>.</P>
<P><SPAN class="command"><STRONG>--dn&nbsp;</STRONG></SPAN><SPAN class=
"emphasis"><EM>&lt;distinguished-name&gt;</EM></SPAN> - specifies the Distinguished
Name for the admin user and is required for
<SPAN class="command"><STRONG>--auth&nbsp;pki</STRONG></SPAN>.</P>
<P><SPAN class="command"><STRONG>port=</STRONG></SPAN><SPAN class=
"emphasis"><EM>portnum</EM></SPAN> - specifies the port the PostgreSQL server will
<P><SPAN class="command"><STRONG>--port|-p&nbsp;</STRONG></SPAN><SPAN class=
"emphasis"><EM>&lt;portnum&gt;</EM></SPAN> - specifies the port the PostgreSQL server will
listen on. For port numbers other than the default 5432, URLs and other
command-lines must explicitly specify the port, when connecting to the server. This
option only effects the initial start of a server. For subsequent (re)starts this
@ -143,10 +145,10 @@
(read-only) privileges, unless a subsequent <SPAN class=
"command"><STRONG>changeprivilege</STRONG></SPAN> command is used.</P>
<P><SPAN class="command"><STRONG>dn=</STRONG></SPAN><SPAN class=
"emphasis"><EM>name</EM></SPAN> - specifies the Distinguished Name of the new user,
<P><SPAN class="command"><STRONG>--dn&nbsp;</STRONG></SPAN><SPAN class=
"emphasis"><EM>&lt;distinguished-name&gt;</EM></SPAN> - specifies the Distinguished Name of the new user,
which is required if the database enabled <SPAN class=
"command"><STRONG>auth=pki</STRONG></SPAN>. This option can be used to provide a
"command"><STRONG>--auth&nbsp;pki</STRONG></SPAN>. This option can be used to provide a
Distinguished Name to a preexisting user, if the PostgreSQL server's authentication
strategy is changed.</P>
</DD>
@ -170,23 +172,22 @@
the same meaning as for the <SPAN class="command"><STRONG>start</STRONG></SPAN>
command.</P>
<P><SPAN class="command"><STRONG>port=</STRONG></SPAN><SPAN class=
"emphasis"><EM>portnum</EM></SPAN> - changes the port the PostgreSQL server will
<P><SPAN class="command"><STRONG>--port|-p&nbsp;</STRONG></SPAN><SPAN class=
"emphasis"><EM>&lt;portnum&gt;</EM></SPAN> - changes the port the PostgreSQL server will
listen on. If this option is not present, the server will continue to listen on the
same port.</P>
<P><SPAN class="command"><STRONG>auth=</STRONG></SPAN><SPAN class=
"emphasis"><EM>type</EM></SPAN> - changes the authentication type (<B>pki |
<P><SPAN class="command"><STRONG>--auth|-a&nbsp;</STRONG></SPAN><SPAN class=
"emphasis"><EM>&lt;type&gt;</EM></SPAN> - changes the authentication type (<B>pki |
password | trust</B>) used by the PostgreSQL server. No change is made if the
option is not present. If the option is present, omitting the <SPAN class=
"command"><STRONG>--noLocalAuth</STRONG></SPAN> causes local connections to require
authentication. This command does not affect the presence or absence of passwords
or Distinguished Names for existing users.</P>
<P><SPAN class="command"><STRONG>dn=</STRONG></SPAN><SPAN class=
"emphasis"><EM>name</EM></SPAN> - specifies the Distinguished Name for the admin
user and is required for <SPAN class=
"command"><STRONG>auth=pki</STRONG></SPAN>.</P>
<P><SPAN class="command"><STRONG>--dn&nbsp;</STRONG></SPAN><SPAN class=
"emphasis"><EM>&lt;distinguished-name&gt;</EM></SPAN> - specifies the Distinguished Name for the admin
user and is required for <SPAN class="command"><STRONG>--auth&nbsp;pki</STRONG></SPAN>.</P>
</DD>
<DT><SPAN class="term"><SPAN class=
@ -219,16 +220,16 @@
"command"><STRONG>resetpassword</STRONG></SPAN>, and <SPAN class=
"command"><STRONG>changeprivilege</STRONG></SPAN>.</P>
<P><SPAN class="command"><STRONG>port=</STRONG></SPAN><SPAN class=
"emphasis"><EM>portnum</EM></SPAN> - specifies the port on which to connect with
<P><SPAN class="command"><STRONG>--port|-p&nbsp;</STRONG></SPAN><SPAN class=
"emphasis"><EM>&lt;portnum&gt;</EM></SPAN> - specifies the port on which to connect with
the PostgreSQL server.</P>
<P><SPAN class="command"><STRONG>user=</STRONG></SPAN><SPAN class=
"emphasis"><EM>username</EM></SPAN> - specifies a user name to use when connecting
<P><SPAN class="command"><STRONG>--user|-u&nbsp;</STRONG></SPAN><SPAN class=
"emphasis"><EM>&lt;username&gt;</EM></SPAN> - specifies a user name to use when connecting
to the PostgreSQL server.</P>
<P><SPAN class="command"><STRONG>cert=</STRONG></SPAN><SPAN class=
"emphasis"><EM>/certfile-path</EM></SPAN> - provides the absolute file path to the
<P><SPAN class="command"><STRONG>--cert&nbsp;</STRONG></SPAN><SPAN class=
"emphasis"><EM>&lt;/certfile-path&gt;</EM></SPAN> - provides the absolute file path to the
user's certificate when connecting to a PostgreSQL server that requires PKI
authentication.</P>
</DD>
@ -249,31 +250,31 @@
<DIV class="informalexample">
<PRE>
<CODE class="computeroutput">
bsim createdatabase &lt;bsimURL&gt; &lt;config_template&gt; [name="&lt;name&gt;"] [owner="&lt;owner&gt;"] [description="&lt;text&gt;"] [--nocallgraph]
bsim setmetadata &lt;bsimURL&gt; [name="&lt;name&gt;"] [owner="&lt;owner&gt;"] [description="&lt;text&gt;"]\n" +
<CODE class&nbsp;"computeroutput">
bsim createdatabase &lt;bsimURL&gt; &lt;config_template&gt; [--name|-n&nbsp;"&lt;name&gt;"] [--owner|-o&nbsp;"&lt;owner&gt;"] [--description|-d&nbsp;"&lt;text&gt;"] [--nocallgraph]
bsim setmetadata &lt;bsimURL&gt; [--name|-n&nbsp;"&lt;name&gt;"] [--owner|-o&nbsp;"&lt;owner&gt;"] [--description|-d&nbsp;"&lt;text&gt;"]\n" +
bsim addexecategory &lt;bsimURL&gt; &lt;category_name&gt; [--date]
bsim addfunctiontag &lt;bsimURL&gt; &lt;tag_name&gt;
bsim dropindex &lt;bsimURL&gt;
bsim rebuildindex &lt;bsimURL&gt;
bsim prewarm &lt;bsimURL&gt;
bsim generatesigs &lt;ghidraURL&gt; &lt;/xmldirectory&gt; config=&lt;config_template&gt; [--overwrite]
bsim generatesigs &lt;ghidraURL&gt; &lt;/xmldirectory&gt; bsim=&lt;bsimURL&gt; [--commit] [--overwrite]
bsim generatesigs &lt;ghidraURL&gt; bsim=&lt;bsimURL&gt;
bsim commitsigs &lt;bsimURL&gt; &lt;/xmldirectory&gt; [md5=&lt;hash&gt;] [override=&lt;ghidraURL&gt;]
bsim generateupdates &lt;ghidraURL&gt; &lt;/xmldirectory&gt; config=&lt;config_template&gt; [--overwrite]
bsim generateupdates &lt;ghidraURL&gt; &lt;/xmldirectory&gt; bsim=&lt;bsimURL&gt; [--commit] [--overwrite]
bsim generateupdates &lt;ghidraURL&gt; bsim=&lt;bsimURL&gt;
bsim generatesigs &lt;ghidraURL&gt; &lt;/xmldirectory&gt; --config|-c&nbsp;&lt;config_template&gt; [--overwrite]
bsim generatesigs &lt;ghidraURL&gt; &lt;/xmldirectory&gt; --bsim|-b&nbsp;&lt;bsimURL&gt; [--commit] [--overwrite]
bsim generatesigs &lt;ghidraURL&gt; --bsim|-b&nbsp;&lt;bsimURL&gt;
bsim commitsigs &lt;bsimURL&gt; &lt;/xmldirectory&gt; [--md5|-m&nbsp;&lt;hash&gt;] [--override&nbsp;&lt;ghidraURL&gt;]
bsim generateupdates &lt;ghidraURL&gt; &lt;/xmldirectory&gt; --config|-c&nbsp;&lt;config_template&gt; [--overwrite]
bsim generateupdates &lt;ghidraURL&gt; &lt;/xmldirectory&gt; --bsim|-b&nbsp;&lt;bsimURL&gt; [--commit] [--overwrite]
bsim generateupdates &lt;ghidraURL&gt; --bsim|-b&nbsp;&lt;bsimURL&gt;
bsim commitupdates &lt;bsimURL&gt; &lt;/xmldirectory&gt;
bsim listexes &lt;bsimURL&gt; [md5=&lt;hash&gt;] [name=&lt;exe_name&gt;] [arch=&lt;languageID&gt;] [compiler=&lt;cspecID&gt;] [sortcol=&lt;column_name&gt;] [limit=&lt;exe_count&gt;] [--includelibs]
bsim getexecount &lt;bsimURL&gt; [md5=&lt;hash&gt;] [name=&lt;exe_name&gt;] [arch=&lt;languageID&gt;] [compiler=&lt;cspecID&gt;] [--includelibs]
bsim delete &lt;bsimURL&gt; [md5=&lt;hash&gt;] [name=&lt;exe_name&gt; [arch=&lt;languageID&gt;] [compiler=&lt;cspecID&gt;]]
bsim listfuncs &lt;bsimURL&gt; [md5=&lt;hash&gt;] [name=&lt;exe_name&gt; [arch=&lt;languageID&gt;] [compiler=&lt;cspecID&gt;]] [--printselfsig] [--callgraph] [--printjustexe] [maxfunc=&lt;max_count&gt;]
bsim dumpsigs &lt;bsimURL&gt; &lt;/xmldirectory&gt; [md5=&lt;hash&gt;] [name=&lt;exe_name&gt; [arch=&lt;languageID&gt;] [compiler=&lt;cspecID&gt;]]
bsim listexes &lt;bsimURL&gt; [--md5|-m&nbsp;&lt;hash&gt;] [--name|-n&nbsp;&lt;exe_name&gt;] [--arch|-a&nbsp;&lt;languageID&gt;] [--compiler&nbsp;&lt;cspecID&gt;] [--sortcol|-s&nbsp;md5|name] [--limit|-l&nbsp;&lt;exe_count&gt;] [--includelibs]
bsim getexecount &lt;bsimURL&gt; [--md5|-m&nbsp;&lt;hash&gt;] [--name|-n&nbsp;&lt;exe_name&gt;] [--arch|-a&nbsp;&lt;languageID&gt;] [--compiler&nbsp;&lt;cspecID&gt;] [--includelibs]
bsim delete &lt;bsimURL&gt; [--md5|-m&nbsp;&lt;hash&gt;] [--name|-n&nbsp;&lt;exe_name&gt; [--arch|-a&nbsp;&lt;languageID&gt;] [--compiler&nbsp;&lt;cspecID&gt;]]
bsim listfuncs &lt;bsimURL&gt; [--md5|-m&nbsp;&lt;hash&gt;] [--name|-n&nbsp;&lt;exe_name&gt; [--arch|-a&nbsp;&lt;languageID&gt;] [--compiler&nbsp;&lt;cspecID&gt;]] [--printselfsig] [--callgraph] [--printjustexe] [--maxfunc&nbsp;&lt;max_count&gt;]
bsim dumpsigs &lt;bsimURL&gt; &lt;/xmldirectory&gt; [--md5|-m&nbsp;&lt;hash&gt;] [--name|-n&nbsp;&lt;exe_name&gt; [--arch|-a&nbsp;&lt;languageID&gt;] [--compiler&nbsp;&lt;cspecID&gt;]]
Global options:
user=&lt;username&gt;
cert=&lt;certfile-path&gt;
--user|-u&nbsp;&lt;username&gt;
--cert&nbsp;&lt;certfile-path&gt;
</CODE>
</PRE>
</DIV>
@ -294,7 +295,12 @@
"command"><STRONG>https:</STRONG></SPAN>, or <SPAN class=
"command"><STRONG>file:</STRONG></SPAN> protocol specified. The <SPAN class=
"command"><STRONG>elastic:</STRONG></SPAN> protocol is equivalent to and may be used in
place of the <SPAN class="command"><STRONG>https:</STRONG></SPAN> protocol.</P>
place of the <SPAN class="command"><STRONG>https:</STRONG></SPAN> protocol.
Optional parameters for a given command are indicated by square brackets '[' and ']'
and always start with either '-' or '--' characters. If an associated value is required
and contains space characters it should be enclosed in double quotes. Options which require
a value may be separated by a space or a equal "=" character (e.g.,
<SPAN class="command"><STRONG>--name=myname</STRONG></SPAN>).</P>
<DIV class="informalexample">
<DIV class="variablelist">
@ -313,19 +319,18 @@
(<SPAN class="bold"><STRONG>large_32, medium_32, medium_64, medium_cpool,
medium_nosize</STRONG></SPAN>).</P>
<P><SPAN class="command"><STRONG>name=</STRONG></SPAN> - specifies a formal, more
<P><SPAN class="command"><STRONG>--name|-n </STRONG></SPAN> - specifies a formal, more
descriptive, name for the repository that can be used for the BSim client
display.</P>
<P><SPAN class="command"><STRONG>owner=</STRONG></SPAN> - gives a descriptive name
<P><SPAN class="command"><STRONG>--owner|-o </STRONG></SPAN> - gives a descriptive name
for the owner of the repository and/or the data it will contain.</P>
<P><SPAN class="command"><STRONG>description=</STRONG></SPAN> - specifies a short
<P><SPAN class="command"><STRONG>--description|-d </STRONG></SPAN> - specifies a short
string describing the intended contents of the new repository.</P>
<P><SPAN class="command"><STRONG>--nocallgraph=</STRONG></SPAN><SPAN class=
"emphasis"><EM>yes/no</EM></SPAN> - disables storing call relationships between
ingested functions. Default is to store call relationships.</P>
<P><SPAN class="command"><STRONG>--nocallgraph</STRONG></SPAN> - disables storing call
relationships between ingested functions. Default is to store call relationships.</P>
</DD>
<DT><SPAN class="term"><SPAN class=
@ -337,14 +342,14 @@
"emphasis"><EM>description</EM></SPAN> metadata associated with a BSim server. A
BSim server URL is required.</P>
<P><SPAN class="command"><STRONG>name=</STRONG></SPAN> - specifies a formal, more
<P><SPAN class="command"><STRONG>--name|-n</STRONG></SPAN> - specifies a formal, more
descriptive, name for the repository that can be used for the BSim client
display.</P>
<P><SPAN class="command"><STRONG>owner=</STRONG></SPAN> - gives a descriptive name
<P><SPAN class="command"><STRONG>--owner|-o</STRONG></SPAN> - gives a descriptive name
for the owner of the repository and/or the data it will contain.</P>
<P><SPAN class="command"><STRONG>description=</STRONG></SPAN> - specifies a short
<P><SPAN class="command"><STRONG>--description|-d</STRONG></SPAN> - specifies a short
string describing the intended contents of the new repository.</P>
</DD>
@ -413,17 +418,16 @@
a Ghidra Server repository or project as specified by a Ghidra URL. The generated
signatures may be retained as XML "sigs_" files within a specified XML storage
directory and/or committed to a specified BSim database specified with the <SPAN
class="command"><STRONG>bsim=</STRONG></SPAN><SPAN class=
"emphasis"><EM>bsimURL</EM></SPAN> option. If an XML storage directory is not
class="command"><STRONG>--bsim</STRONG></SPAN> option. If an XML storage directory is not
specified, a BSim URL must be specified to which the data will be committed.</P>
<P>The <SPAN class="command"><STRONG>config=</STRONG></SPAN><SPAN class=
"emphasis"><EM>config-template</EM></SPAN> option may be specified when generating
<P>The <SPAN class="command"><STRONG>--config|-c&nbsp;</STRONG></SPAN><SPAN class=
"emphasis"><EM>&lt;config-template&gt;</EM></SPAN> option may be specified when generating
XML "sigs_" signature files in the absence of a BSim database (see
<STRONG>createdatabase</STRONG> for supported configurations). The generated files
will be written to the specified XML storage directory. Creation of the signature
files can also be achieved by specifying the <STRONG>bsim=</STRONG><EM>bsimURL</EM>
option instead of the <STRONG>config=</STRONG> option.</P>
files can also be achieved by specifying the <STRONG>--bsim</STRONG>
option instead of the <STRONG>--config</STRONG> option.</P>
<P>The <SPAN class="command"><STRONG>--overwrite</STRONG></SPAN> <SPAN class=
"emphasis">option may be specified when an XML storage directory has also been
@ -444,8 +448,8 @@
repository and a path to a directory containing the "sigs_" XML files to commit are
required.</P>
<P><SPAN class="command"><STRONG>override=</STRONG></SPAN><SPAN class=
"emphasis"><EM>ghidraURL</EM></SPAN> - causes any Ghidra repository/project URL,
<P><SPAN class="command"><STRONG>--override&nbsp;</STRONG></SPAN><SPAN class=
"emphasis"><EM>&lt;ghidraURL&gt;</EM></SPAN> - causes any Ghidra repository/project URL,
describing the storage repository and path of executables that was recorded in the
"sigs_" XML files during signature generation, to be overridden during the commit
operation with the specified Ghidra URL.</P>
@ -461,17 +465,16 @@
function tags, categories, etc. are changed. Signatures are not affected. The
generated updates may be retained as XML "update_" files within a specified XML
storage directory and/or committed to a specified BSim database specified with the
<SPAN class="command"><STRONG>bsim=</STRONG></SPAN><SPAN class=
"emphasis"><EM>bsimURL</EM></SPAN> option. If an XML storage directory is not
<SPAN class="command"><STRONG>--bsim</STRONG></SPAN> option. If an XML storage directory is not
specified, a BSim URL must be specified to which the data will be committed.</P>
<P>The <SPAN class="command"><STRONG>config=</STRONG></SPAN><SPAN class=
"emphasis"><EM>config-template</EM></SPAN> option may be specified when generating
<P>The <SPAN class="command"><STRONG>--config|-c&nbsp;</STRONG></SPAN><SPAN class=
"emphasis"><EM>&lt;config-template&gt;</EM></SPAN> option may be specified when generating
XML "update_" files in the absence of a BSim database (see
<STRONG>createdatabase</STRONG> for supported configurations). The generated files
will be written to the specified XML storage directory. Creation of the update
files can also be achieved by specifying the <STRONG>bsim=</STRONG><EM>bsimURL</EM>
option instead of the <STRONG>config=</STRONG> option.</P>
files can also be achieved by specifying the <STRONG>--bsim</STRONG>
option instead of the <STRONG>--config</STRONG> option.</P>
<P>The <SPAN class="command"><STRONG>--overwrite</STRONG></SPAN> <SPAN class=
"emphasis">option may be specified when an XML storage directory has also been
@ -499,30 +502,27 @@
<P>List all executable program records within a specified BSim database repository
which satisfy the specified criteria. A BSim URL specifying the repository must be
provided, and one of two options, <SPAN class=
"command"><STRONG>md5=</STRONG></SPAN> or <SPAN class=
"command"><STRONG>name=</STRONG></SPAN>, that indicate the specific executable must
"command"><STRONG>--md5</STRONG></SPAN> or <SPAN class=
"command"><STRONG>--name </STRONG></SPAN>, that indicate the specific executable must
also be given. All matching executable records will be listed.</P>
<P><SPAN class="command"><STRONG>md5=</STRONG></SPAN><SPAN class=
"emphasis"><EM>32-hexdigits</EM></SPAN> - specifies an executable via its MD5
checksum.</P>
<P><SPAN class="command"><STRONG>--md5|-m</STRONG></SPAN> - specifies an executable via its MD5
checksum as 32 hexidecimal digits.</P>
<P><SPAN class="command"><STRONG>name=</STRONG></SPAN> - specifies an executable
<P><SPAN class="command"><STRONG>--name|-n</STRONG></SPAN> - specifies an executable
name which may match one or more executable records.</P>
<P><SPAN class="command"><STRONG>arch=</STRONG></SPAN> - specifies an architecture
<P><SPAN class="command"><STRONG>--arch|-a</STRONG></SPAN> - specifies an architecture
as a Ghidra processor id which will be used to filter executables.</P>
<P><SPAN class="command"><STRONG>compiler=</STRONG></SPAN> - specifies a compiler
<P><SPAN class="command"><STRONG>--compiler</STRONG></SPAN> - specifies a compiler
specification id which will be used to filter executables.</P>
<P><SPAN class="command"><STRONG>sortcol=</STRONG></SPAN><SPAN class=
"emphasis"><EM>column</EM></SPAN> - Indicates which display column should be used
to sort the results (<STRONG>MD5 | NAME</STRONG>; default:
<STRONG>MD5</STRONG>).</P>
<P><SPAN class="command"><STRONG>--sortcol|-s</STRONG></SPAN> - Specifies which display
column should be used to sort the results (<STRONG>md5 | name</STRONG>; default:
<STRONG>md5</STRONG>).</P>
<P><SPAN class="command"><STRONG>limit=</STRONG></SPAN><SPAN class=
"emphasis"><EM>max_count</EM></SPAN> - specifies the maximum number of executables
<P><SPAN class="command"><STRONG>--limit|-l</STRONG></SPAN> - specifies the maximum number of executables
to be listed which match the search criteria (default=20, a value of 0 indicates no
limit).</P>
@ -538,21 +538,20 @@
<P>Get the total number of executable program records within a specified BSim
database repository which satisfy the specified criteria. A BSim URL specifying the
repository must be provided, and one of two options, <SPAN class=
"command"><STRONG>md5=</STRONG></SPAN> or <SPAN class=
"command"><STRONG>name=</STRONG></SPAN>, that indicate the specific executable must
"command"><STRONG>--md5</STRONG></SPAN> or <SPAN class=
"command"><STRONG>--name</STRONG></SPAN>, that indicate the specific executable must
also be given. All matching executable records will be listed.</P>
<P><SPAN class="command"><STRONG>md5=</STRONG></SPAN><SPAN class=
"emphasis"><EM>32-hexdigits</EM></SPAN> - specifies an executable via its MD5
checksum.</P>
<P><SPAN class="command"><STRONG>--md5|-m</STRONG></SPAN> - specifies an executable via its MD5
checksum as 32 hexidecimal digits.</P>
<P><SPAN class="command"><STRONG>name=</STRONG></SPAN> - specifies an executable
<P><SPAN class="command"><STRONG>--name|-n</STRONG></SPAN> - specifies an executable
name which may match one or more executable records.</P>
<P><SPAN class="command"><STRONG>arch=</STRONG></SPAN> - specifies an architecture
<P><SPAN class="command"><STRONG>--arch|-a</STRONG></SPAN> - specifies an architecture
as a Ghidra processor id which will be used to filter executables.</P>
<P><SPAN class="command"><STRONG>compiler=</STRONG></SPAN> - specifies a compiler
<P><SPAN class="command"><STRONG>--compiler</STRONG></SPAN> - specifies a compiler
specification id which will be used to filter executables.</P>
<P><SPAN class="command"><STRONG>--includelibs</STRONG> - If specified, executable
@ -565,26 +564,25 @@
<DD>
<P>Remove all records associated with a specific executable from a BSim repository.
A BSim URL specifying the repository must be provided, and one of two options,
<SPAN class="command"><STRONG>md5=</STRONG></SPAN> or <SPAN class=
"command"><STRONG>name=</STRONG></SPAN>, that indicate the specific executable must
<SPAN class="command"><STRONG>--md5</STRONG></SPAN> or <SPAN class=
"command"><STRONG>--name</STRONG></SPAN>, that indicate the specific executable must
also be given. All associated executable and function records are removed.
If an executable cannot be uniquely identified an error will result.
</P>
<P><SPAN class="command"><STRONG>md5=</STRONG></SPAN><SPAN class=
"emphasis"><EM>32-hexdigits</EM></SPAN> - specifies the executable via its MD5
checksum.</P>
<P><SPAN class="command"><STRONG>--md5|-m</STRONG></SPAN> - specifies an executable via its MD5
checksum as 32 hexidecimal digits.</P>
<P><SPAN class="command"><STRONG>name=</STRONG></SPAN> - specifies an executable
<P><SPAN class="command"><STRONG>--name|-n</STRONG></SPAN> - specifies an executable
name which may match one or more executable records.</P>
<P><SPAN class="command"><STRONG>arch=</STRONG></SPAN> - specifies an architecture
<P><SPAN class="command"><STRONG>--arch|-a</STRONG></SPAN> - specifies an architecture
as a Ghidra processor id, when the <SPAN class=
"command"><STRONG>name</STRONG></SPAN> option is not enough to uniquely specify the
"command"><STRONG>--name</STRONG></SPAN> option is not enough to uniquely specify the
executable.</P>
<P><SPAN class="command"><STRONG>compiler=</STRONG></SPAN> - specifies a compiler
id string, when the <SPAN class="command"><STRONG>name</STRONG></SPAN> option is
<P><SPAN class="command"><STRONG>--compiler</STRONG></SPAN> - specifies a compiler
id string, when the <SPAN class="command"><STRONG>--name</STRONG></SPAN> option is
not enough to uniquely specify the executable.</P>
</DD>
@ -594,25 +592,24 @@
<DD>
<P>List all function records associated with a specific executable from a BSim
repository. A BSim URL specifying the repository must be provided, and one of two
options, <SPAN class="command"><STRONG>md5=</STRONG></SPAN> or <SPAN class=
"command"><STRONG>name=</STRONG></SPAN>, that indicate the specific executable must
options, <SPAN class="command"><STRONG>--md5</STRONG></SPAN> or <SPAN class=
"command"><STRONG>--name</STRONG></SPAN>, that indicate the specific executable must
also be given. All associated executable and function records are listed. If an
executable cannot be uniquely identified an error will result.</P>
<P><SPAN class="command"><STRONG>md5=</STRONG></SPAN><SPAN class=
"emphasis"><EM>32-hexdigits</EM></SPAN> - specifies the executable via its MD5
checksum.</P>
<P><SPAN class="command"><STRONG>--md5|-m</STRONG></SPAN> - specifies an executable via its MD5
checksum as 32 hexidecimal digits.</P>
<P><SPAN class="command"><STRONG>name=</STRONG></SPAN> - specifies an executable
<P><SPAN class="command"><STRONG>--name|-n</STRONG></SPAN> - specifies an executable
name which may match one or more executable records.</P>
<P><SPAN class="command"><STRONG>arch=</STRONG></SPAN> - specifies an architecture
<P><SPAN class="command"><STRONG>--arch|-a</STRONG></SPAN> - specifies an architecture
as a Ghidra processor id, when the <SPAN class=
"command"><STRONG>name</STRONG></SPAN> option is not enough to uniquely specify the
"command"><STRONG>--name</STRONG></SPAN> option is not enough to uniquely specify the
executable.</P>
<P><SPAN class="command"><STRONG>compiler=</STRONG></SPAN> - specifies a compiler
id string, when the <SPAN class="command"><STRONG>name</STRONG></SPAN> option is
<P><SPAN class="command"><STRONG>--compiler</STRONG></SPAN> - specifies a compiler
id string, when the <SPAN class="command"><STRONG>--name</STRONG></SPAN> option is
not enough to uniquely specify the executable.</P>
<P><SPAN class="command"><STRONG>--printselfsig</STRONG></SPAN> - If specified, each
@ -628,8 +625,7 @@
also specified only the called libraries will be listed and not the specified
functions.</SPAN></P>
<P><SPAN class="command"><STRONG>maxfunc=</STRONG></SPAN><SPAN class=
"emphasis"><EM>max_count</EM></SPAN> - specifies the maximum number of functions to
<P><SPAN class="command"><STRONG>--maxfunc</STRONG></SPAN> - specifies the maximum number of functions to
be listed which correspond to the identified executable (default=1000, a value of 0
indicates no limit).</P>
</DD>
@ -641,25 +637,24 @@
<P>Dump signature and metadata from a BSim repository for a specific executable to
a "sigs_" XML file. A BSim server URL and a path to a directory where the new file
will be stored must be given. One of two options, <SPAN class=
"command"><STRONG>md5=</STRONG></SPAN> or <SPAN class=
"command"><STRONG>name=</STRONG></SPAN>, that specify the particular executable
"command"><STRONG>--md5</STRONG></SPAN> or <SPAN class=
"command"><STRONG>--name</STRONG></SPAN>, that specify the particular executable
must also be given. If an executable cannot be uniquely identified an error will result.</P>
<P><SPAN class="command"><STRONG>md5=</STRONG></SPAN><SPAN class=
"emphasis"><EM>32-hexdigits</EM></SPAN> - specifies an executable via its MD5
checksum.</P>
<P><SPAN class="command"><STRONG>--md5|-m</STRONG></SPAN> - specifies an executable via its MD5
checksum as 32 hexidecimal digits.</P>
<P><SPAN class="command"><STRONG>name=</STRONG></SPAN> - specifies an executable
<P><SPAN class="command"><STRONG>--name|-n</STRONG></SPAN> - specifies an executable
name which may match one or more executable records.</P>
<P><SPAN class="command"><STRONG>arch=</STRONG></SPAN> - specifies an architecture
<P><SPAN class="command"><STRONG>--arch|-a</STRONG></SPAN> - specifies an architecture
as a Ghidra processor id, when the <SPAN class=
"command"><STRONG>name</STRONG></SPAN> option is not enough to uniquely specify the
"command"><STRONG>--name</STRONG></SPAN> option is not enough to uniquely specify the
executable.</P>
<P><SPAN class="command"><STRONG>compiler=</STRONG></SPAN> - specifies a compiler
<P><SPAN class="command"><STRONG>--compiler</STRONG></SPAN> - specifies a compiler
specification id, when the <SPAN class=
"command"><STRONG>name</STRONG></SPAN> option is not enough to uniquely specify the
"command"><STRONG>--name</STRONG></SPAN> option is not enough to uniquely specify the
executable.</P>
</DD>
@ -671,12 +666,12 @@
<P>These options apply to all <SPAN class="command"><STRONG>bsim</STRONG></SPAN>
commands.</P>
<P><SPAN class="command"><STRONG>user=</STRONG></SPAN><SPAN class=
"emphasis"><EM>name</EM></SPAN> - specifies a user to masquerade as when connecting
<P><SPAN class="command"><STRONG>--user|-u&nbsp;</STRONG></SPAN><SPAN class=
"emphasis"><EM>&lt;username&gt;</EM></SPAN> - specifies a user to masquerade as when connecting
to the server.</P>
<P><SPAN class="command"><STRONG>cert=</STRONG></SPAN><SPAN class=
"emphasis"><EM>path</EM></SPAN> - provides a path to the user's certificate when
<P><SPAN class="command"><STRONG>--cert&nbsp;</STRONG></SPAN><SPAN class=
"emphasis"><EM>&lt;certfile-path&gt;</EM></SPAN> - provides a path to the user's certificate when
connecting to a server that requires PKI authentication.</P>
</DD>
</DL>

View File

@ -214,7 +214,7 @@
<TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim_ctl start /path/to/datadir
port=8000</CODE></TD>
--port&nbsp;8000</CODE></TD>
</TR>
<TR>
@ -236,7 +236,7 @@
be reused.</P>
<P>The <SPAN class="bold"><STRONG>start</STRONG></SPAN> command can take an optional
<SPAN class="bold"><STRONG>port=</STRONG></SPAN> parameter. This can be used to specify
<SPAN class="bold"><STRONG>--port</STRONG></SPAN> parameter. This can be used to specify
a non-standard port for the PostgreSQL server to listen on. In this case, any
subsequent reference to the BSim server, in the Ghidra client, or with the <SPAN class=
"command"><STRONG>bsim</STRONG></SPAN> command described below, must specify the port.
@ -293,7 +293,7 @@
<DD>
<P><CODE class="computeroutput">bsim_ctl start /path/to/datadir
auth=trust</CODE></P>
--auth&nbsp;trust</CODE></P>
<P>This is currently the default. No authentication is performed and privilege
is granted based on the user name presented. Masquerading is possible.</P>
@ -304,7 +304,7 @@
<DD>
<P><CODE class="computeroutput">bsim_ctl start /path/to/datadir
auth=password</CODE></P>
--auth&nbsp;password</CODE></P>
<P>Users are authenticated via password. A default password 'changeme' is
established when the new user is created. Passwords can be changed by the user
@ -315,12 +315,12 @@
<DT><SPAN class="term"><SPAN class="bold"><STRONG>pki</STRONG></SPAN></SPAN></DT>
<DD>
<P><CODE class="computeroutput">bsim_ctl start /path/to/datadir auth=pki
ca=/path/to/rootcert</CODE></P>
<P><CODE class="computeroutput">bsim_ctl start /path/to/datadir --auth&nbsp;pki
--cafile&nbsp;"/path/to/rootcert"</CODE></P>
<P>Users are authenticated by PKI certificates. Upon initialization, the BSim
server must be provided (via the <SPAN class=
"command"><STRONG>ca=</STRONG></SPAN> option) a file containing the public keys
"command"><STRONG>--cafile</STRONG></SPAN> option) a file containing the public keys
for the certificate authorities used to issue user's certificates. The file
consists of the authoritative certificates in PEM format concatenated
together.</P>
@ -338,7 +338,7 @@
<P>With PKI authentication enabled, at the time a new user role is established
with the server, the X.509 Distinguished Name, as bound to the user's
certificate, must be associated with the user name via the <SPAN class=
"command"><STRONG>dn=</STRONG></SPAN> option. See <A class="xref" href=
"command"><STRONG>--dn</STRONG></SPAN> option. See <A class="xref" href=
"#PostAddUser" title="Adding Users to the Database">&ldquo;Adding Users to the
Database&rdquo;</A>.</P>
</DD>
@ -358,7 +358,7 @@
<TABLE border="0" summary="Simple list" class="simplelist">
<TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim_ctl changeauth
/datadir/path auth=password</CODE></TD>
/datadir/path --auth&nbsp;password</CODE></TD>
</TR>
</TABLE>
</DIV>
@ -401,7 +401,7 @@
<TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim_ctl adduser <SPAN class=
"emphasis"><EM>username</EM></SPAN> dn="C=US,ST=MD,CN=Firstname User"</CODE></TD>
"emphasis"><EM>username</EM></SPAN> --dn&nbsp;"C=US,ST=MD,CN=Firstname User"</CODE></TD>
</TR>
</TABLE>
</DIV>
@ -410,7 +410,7 @@
initially be set to 'changeme'. If PKI authentication has been set for the server, The
Distinguished Name, as bound to the new user's certificated must be provided when
issuing the <SPAN class="command"><STRONG>adduser</STRONG></SPAN> command, via the
<SPAN class="command"><STRONG>dn=</STRONG></SPAN> option. The Distinguished Name must
<SPAN class="command"><STRONG>--dn</STRONG></SPAN> option. The Distinguished Name must
be presented as a string containing a comma separated sequence of attribute/value pairs
that uniquely identifies a certificate. Currently, the Common Name (CN=) is the only
attribute inspected by the PostgreSQL server, so other attributes can be omitted.</P>
@ -836,17 +836,17 @@ curl -k -u elastic:XXXXXX -X POST "https://localhost:9200/_security/user/ghidrau
<TABLE border="0" summary="Simple list" class="simplelist">
<TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim setmetadata <SPAN class=
"emphasis"><EM>bsimURL</EM></SPAN> "name=BSim Database"</CODE></TD>
"emphasis"><EM>bsimURL</EM></SPAN> --name&nbsp;"BSim Database"</CODE></TD>
</TR>
<TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim setmetadata <SPAN class=
"emphasis"><EM>bsimURL</EM></SPAN> "owner=Administrators"</CODE></TD>
"emphasis"><EM>bsimURL</EM></SPAN> --owner&nbsp;"Administrators"</CODE></TD>
</TR>
<TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim setmetadata <SPAN class=
"emphasis"><EM>bsimURL</EM></SPAN> "description=Files of interest"</CODE></TD>
"emphasis"><EM>bsimURL</EM></SPAN> --description&nbsp;"Files of interest"</CODE></TD>
</TR>
</TABLE>
</DIV>
@ -855,8 +855,8 @@ curl -k -u elastic:XXXXXX -X POST "https://localhost:9200/_security/user/ghidrau
changed at any time and do not otherwise affect the records contained in the database.
Multiple command-line parameters can be fed to <SPAN class="command"><STRONG>bsim
setmetadata</STRONG></SPAN> so long as each one starts with <SPAN class=
"bold"><STRONG>name=</STRONG></SPAN>, <SPAN class="bold"><STRONG>owner=</STRONG></SPAN>, or
<SPAN class="bold"><STRONG>description=</STRONG></SPAN> respectively. Quoting may be
"bold"><STRONG>--name</STRONG></SPAN>, <SPAN class="bold"><STRONG>--owner</STRONG></SPAN>, or
<SPAN class="bold"><STRONG>--description</STRONG></SPAN> respectively. Quoting of values may be
necessary to get some strings to be interpreted as a single command-line parameter.</P>
<DIV class="sect2">

View File

@ -112,20 +112,20 @@
"command"><STRONG>bsim generatesigs</STRONG></SPAN> command. Signatures may be written as
XML files to a local directory and/or committed directly to a specified BSim database. If
not immediately committing to a database and only storing the XML files an appropriate
database <EM>config=</EM> may be specified in lieu of a BSim database URL
(<EM>bsimURL</EM>) if database specific executable categories and function tags are not
utilized. Use of the <EM>config=</EM> option does not require a running BSim server.</P>
database configuration may be specified using the <EM>--config</EM> option in lieu of a BSim database URL
(--bsim <EM>&lt;bsimURL&gt;</EM>) if database specific executable categories and function tags are not
utilized. Use of the <EM>--config</EM> option does not require a running BSim server.</P>
<DIV class="informalexample">
<TABLE border="0" summary="Simple list" class="simplelist">
<TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim generatesigs
&lt;ghidraURL&gt; &lt;/xmldirectory&gt; config=&lt;config_template&gt;
&lt;ghidraURL&gt; &lt;/xmldirectory&gt; --config&nbsp;&lt;config_template&gt;
[--overwrite]<BR>
$(ROOT)/support/bsim generatesigs &lt;ghidraURL&gt; &lt;/xmldirectory&gt;
bsim=&lt;bsimURL&gt; [--commit] [--overwrite]<BR>
--bsim&nbsp;&lt;bsimURL&gt; [--commit] [--overwrite]<BR>
$(ROOT)/support/bsim generatesigs &lt;ghidraURL&gt;
bsim=&lt;bsimURL&gt;</CODE></TD>
--bsim&nbsp;&lt;bsimURL&gt;</CODE></TD>
</TR>
</TABLE>
</DIV>
@ -137,7 +137,7 @@
<TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim generatesigs
ghidra://localhost/repo/folder /xmldirectory
bsim=postgresql://localhost/repo</CODE></TD>
--bsim&nbsp;postgresql://localhost/repo</CODE></TD>
</TR>
</TABLE>
</DIV>
@ -148,7 +148,7 @@
<TABLE border="0" summary="Simple list" class="simplelist">
<TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim generatesigs
ghidra://localhost/repo/folder /xmldirectory bsim=postgresql://localhost/repo
ghidra://localhost/repo/folder /xmldirectory --bsim&nbsp;postgresql://localhost/repo
--commit</CODE></TD>
</TR>
</TABLE>
@ -176,7 +176,7 @@
the signature generation process, such as database specific executable categories or
function tags. As in the example above, configuration information
is pulled from the BSim server and signatures are generated from the Ghidra Server
executables. If the <SPAN class="bold"><STRONG>config=</STRONG></SPAN>
executables. If the <SPAN class="bold"><STRONG>--config</STRONG></SPAN>
option is used, assuming the template it specifies is the same one used to create the
database and there are no executable categories or function tags, the BSim server
does not need to be running.</P>
@ -199,7 +199,7 @@
<TABLE border="0" summary="Simple list" class="simplelist">
<TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim commitsigs
postgresql://localhost/repo /xmldirectory [override=<EM>ghidraURL</EM>]</CODE></TD>
postgresql://localhost/repo /xmldirectory [--override&nbsp;<EM>&lt;ghidraURL&gt;</EM>]</CODE></TD>
</TR>
</TABLE>
</DIV>
@ -215,7 +215,7 @@
"emphasis"><EM>repository</EM></SPAN> and <SPAN class="emphasis"><EM>path</EM></SPAN>
associated with it in the form of a <SPAN class="emphasis"><EM>ghidra://</EM></SPAN> URL
that was recorded when the XML files were generated. This path can be overridden with the
optional <SPAN class="bold"><STRONG>override=</STRONG></SPAN> parameter where a revised
optional <SPAN class="bold"><STRONG>--override</STRONG></SPAN> option where a revised
Ghidra URL may be specified.</P>
<P>The <SPAN class="command"><STRONG>bsim commitsigs</STRONG></SPAN> command can be
@ -526,21 +526,21 @@ public void adjustTags(Address myaddress) throws Exception {
<TABLE border="0" summary="Simple list" class="simplelist">
<TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim delete <SPAN class=
"emphasis"><EM>bsimURL</EM></SPAN> md5=<SPAN class=
"emphasis"><EM>&lt;bsimURL&gt;</EM></SPAN> --md5&nbsp;<SPAN class=
"emphasis"><EM>7abf...</EM></SPAN></CODE></TD>
</TR>
<TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim delete <SPAN class=
"emphasis"><EM>bsimURL</EM></SPAN> name=<SPAN class=
"emphasis"><EM>&lt;bsimURL&gt;</EM></SPAN> --name&nbsp;<SPAN class=
"emphasis"><EM>...</EM></SPAN></CODE></TD>
</TR>
</TABLE>
</DIV>
<P>In the <SPAN class="emphasis"><EM>md5</EM></SPAN> form, you specify the 32 character
<P>In the <SPAN class="emphasis"><EM>--md5</EM></SPAN> form, you specify the 32 character
hex representation of the md5 hash of the executable, which should identify it
uniquely. Using the <SPAN class="emphasis"><EM>name</EM></SPAN> form, there is the
uniquely. Using the <SPAN class="emphasis"><EM>--name</EM></SPAN> form, there is the
possibility that the name is not unique, in which case the command will fail.</P>
<P>If a unique executable is identified, its metadata record will be removed, and the
@ -580,11 +580,11 @@ public void adjustTags(Address myaddress) throws Exception {
<TABLE border="0" summary="Simple list" class="simplelist">
<TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim generateupdates
&lt;ghidraURL&gt; &lt;/xmldirectory&gt; config=&lt;config_template&gt;
&lt;ghidraURL&gt; &lt;/xmldirectory&gt; --config&nbsp;&lt;config_template&gt;
[--overwrite]<BR>
$(ROOT)/support/bsim generateupdates &lt;ghidraURL&gt; &lt;/xmldirectory&gt;
bsim=&lt;bsimURL&gt; [--commit] [--overwrite]<BR>
$(ROOT)/support/bsim generateupdates &lt;ghidraURL&gt; bsim=&lt;bsimURL&gt;<BR>
--bsim&nbsp;&lt;bsimURL&gt; [--commit] [--overwrite]<BR>
$(ROOT)/support/bsim generateupdates &lt;ghidraURL&gt; --bsim&nbsp;&lt;bsimURL&gt;<BR>
<BR>
$(ROOT)/support/bsim commitupdates &lt;bsimURL&gt;
&lt;/xmldirectory&gt;</CODE></TD>
@ -596,11 +596,13 @@ public void adjustTags(Address myaddress) throws Exception {
stripped down metadata XML files for every executable contained within the repository
folder specified by the <EM>ghidraURL</EM>. Just like the <SPAN class=
"bold"><STRONG>generatesigs</STRONG></SPAN> command, it can take an optional <SPAN
class="bold"><STRONG>config=<EM>config_template</EM></STRONG></SPAN> parameter, which
allows the command to execute without the BSim server running. It can also take an
class="bold"><STRONG>--config&nbsp;<EM>&lt;config_template&gt;</EM></STRONG></SPAN> parameter, which
allows the command to execute without the BSim server running, otherwise a <SPAN
class="bold"><STRONG>--bsim&nbsp;<EM>&lt;bsimURL&gt;</EM></STRONG></SPAN>
parameter is required. It can also take an
optional <SPAN class="bold"><STRONG>--overwrite</STRONG></SPAN> parameter, causing it
to overwrite any previously generated XML files. If a
<STRONG>bsim=<EM>bsimURL</EM></STRONG> is specified with the <STRONG>--commit</STRONG>
to overwrite any previously generated XML files. If the
<STRONG>--bsim</STRONG> option is specified with the <STRONG>--commit</STRONG>
option updates will be committed directly to the database. A BSim database commit is
always performed using the specified <EM>bsimURL</EM> if an <EM>xmldirectory</EM> is
not specified.</P>
@ -635,7 +637,7 @@ public void adjustTags(Address myaddress) throws Exception {
<TABLE border="0" summary="Simple list" class="simplelist">
<TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim dropindex <SPAN class=
"emphasis"><EM>bsimURL</EM></SPAN></CODE></TD>
"emphasis"><EM>&lt;bsimURL&gt;</EM></SPAN></CODE></TD>
</TR>
</TABLE>
</DIV>
@ -646,7 +648,7 @@ public void adjustTags(Address myaddress) throws Exception {
<TABLE border="0" summary="Simple list" class="simplelist">
<TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim rebuildindex <SPAN class=
"emphasis"><EM>bsimURL</EM></SPAN></CODE></TD>
"emphasis"><EM>&lt;bsimURL&gt;</EM></SPAN></CODE></TD>
</TR>
</TABLE>
</DIV>

View File

@ -29,6 +29,7 @@ import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import javax.security.auth.DestroyFailedException;
import org.apache.commons.lang3.StringUtils;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
@ -40,7 +41,7 @@ import ghidra.framework.client.ClientUtil;
import ghidra.net.ApplicationKeyManagerUtils;
import ghidra.util.Msg;
import ghidra.util.exception.AssertException;
import ghidra.util.task.TaskMonitor;
import ghidra.util.exception.CancelledException;
import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.NonThreadedXmlPullParserImpl;
import ghidra.xml.XmlPullParser;
@ -48,22 +49,68 @@ import utilities.util.FileUtilities;
public class BSimControlLaunchable implements GhidraLaunchable {
public static final String PORT_OPTION = "port=";
public static final String CAFILE_OPTION = "cafile=";
public static final String AUTH_OPTION = "auth=";
public static final String DN_OPTION = "dn=";
public static final String CERT_OPTION = "cert=";
// bsim_ctl commands
public final static String COMMAND_START = "start";
public final static String COMMAND_STOP = "stop";
public final static String COMMAND_RESET_PASSWORD = "resetpassword";
public final static String COMMAND_CHANGE_PRIVILEGE = "changeprivilege";
public final static String COMMAND_ADDUSER = "adduser";
public final static String COMMAND_DROPUSER = "dropuser";
public final static String COMMAND_CHANGEAUTH = "changeauth";
// Options that require a value argument
public static final String CAFILE_OPTION = "--cafile";
public static final String AUTH_OPTION = "--auth";
public static final String DN_OPTION = "--dn";
// Global options that require a value argument
public static final String PORT_OPTION = "--port";
public static final String USER_OPTION = "--user";
public static final String CERT_OPTION = "--cert";
// Define set of options that require a second value argument
private static final Set<String> VALUE_OPTIONS =
Set.of(PORT_OPTION, USER_OPTION, CERT_OPTION, CAFILE_OPTION, AUTH_OPTION, DN_OPTION);
private static final Set<String> GLOBAL_OPTIONS = Set.of(PORT_OPTION, USER_OPTION, CERT_OPTION);
// Boolean options
public static final String NO_LOCAL_AUTH_OPTION = "--noLocalAuth";
public static final String USER_OPTION = "user=";
public static final String FORCE_OPTION = "--force";
private final static String START_COMMAND = "start";
private final static String STOP_COMMAND = "stop";
private final static String PASSWORD_COMMAND = "resetpassword";
private final static String PRIVILEGE_COMMAND = "changeprivilege";
private final static String ADDUSER_COMMAND = "adduser";
private final static String DROPUSER_COMMAND = "dropuser";
private final static String RESET_COMMAND = "changeauth";
private static final Map<String, String> SHORTCUT_OPTION_MAP = new HashMap<>();
static {
SHORTCUT_OPTION_MAP.put("-a", AUTH_OPTION);
SHORTCUT_OPTION_MAP.put("-p", PORT_OPTION);
SHORTCUT_OPTION_MAP.put("-u", USER_OPTION);
}
//@formatter:off
// Populate ALLOWED_OPTION_MAP for each command
private static final Set<String> START_OPTIONS =
Set.of(AUTH_OPTION, DN_OPTION, NO_LOCAL_AUTH_OPTION, CAFILE_OPTION);
private static final Set<String> STOP_OPTIONS =
Set.of(FORCE_OPTION);
private static final Set<String> RESET_PASSWORD_OPTIONS = Set.of();
private static final Set<String> CHANGE_PRIVILEGE_OPTIONS = Set.of();
private static final Set<String> ADDUSER_OPTIONS =
Set.of(DN_OPTION);
private static final Set<String> DROPUSER_OPTIONS = Set.of();
private static final Set<String> CHANGEAUTH_OPTIONS = Set.of(
AUTH_OPTION, NO_LOCAL_AUTH_OPTION, CAFILE_OPTION);
//@formatter:on
private static final Map<String, Set<String>> ALLOWED_OPTION_MAP = new HashMap<>();
static {
ALLOWED_OPTION_MAP.put(COMMAND_START, START_OPTIONS);
ALLOWED_OPTION_MAP.put(COMMAND_STOP, STOP_OPTIONS);
ALLOWED_OPTION_MAP.put(COMMAND_RESET_PASSWORD, RESET_PASSWORD_OPTIONS);
ALLOWED_OPTION_MAP.put(COMMAND_CHANGE_PRIVILEGE, CHANGE_PRIVILEGE_OPTIONS);
ALLOWED_OPTION_MAP.put(COMMAND_ADDUSER, ADDUSER_OPTIONS);
ALLOWED_OPTION_MAP.put(COMMAND_DROPUSER, DROPUSER_OPTIONS);
ALLOWED_OPTION_MAP.put(COMMAND_CHANGEAUTH, CHANGEAUTH_OPTIONS);
}
private final static String POSTGRES = "postgresql";
private final static String POSTGRES_BUILD_SCRIPT = "Ghidra/Features/BSim/make-postgres.sh";
private final static String POSTGRES_CONFIGFILE = "postgresql.conf";
@ -80,73 +127,245 @@ public class BSimControlLaunchable implements GhidraLaunchable {
private final static int AUTHENTICATION_NONE = 0;
private final static int AUTHENTICATION_PASSWORD = 1;
private final static int AUTHENTICATION_PKI = 2;
private GhidraApplicationLayout layout = null; // For holding on to JDBC logger so we can filter messages
private File dataDirectory; // Directory containing postgres datafiles
private File postgresRoot; // Directory containing postgres software
private File postgresControl; // "pg_ctl" utility within postgres software
private File certAuthorityFile = null; // Certificate authority file provided by the user
private String certParameter = null; // Path to certificate provided by user
private String distinguishedName = null; // Certificate distinguished name provided by the user
private String commonName = null; // Common name extracted from distinguishedName
private String connectingUserName = null; // User-name used to establish connection
private String specifiedUserName = null; // -username- (add/drop) operation is being performed on
private boolean adminPrivilegeRequested = false; // true is attempting to give user admin privileges
private boolean forceShutdown = false; // Whether or not to force a shutdown (--force)
private String loadLibraryVar = null; // Environment variable pointing to postgres shared libraries
private String loadLibraryValue = null; // Directory containing shared libraries within postgres software
private int port = -1; // Port over which to connect to postgres server, (-1 indicates default port is used)
private int localAuthentication = AUTHENTICATION_NONE; // Type of authentication required for local connections
private int hostAuthentication = AUTHENTICATION_NONE; // Type of authentication for remote connections
private boolean authConfigPresent = false; // True if the [auth=..] option or the [--noLocalAuth] is present
private File passwordFile = null; // File containing newly established password
private char[] adminPasswordData = null; // Password data being sent to postgres server for authentication
private GhidraApplicationLayout layout;
private File dataDirectory; // Directory containing postgres datafiles
private File postgresRoot; // Directory containing postgres software
private File postgresControl; // "pg_ctl" utility within postgres software
private File certAuthorityFile; // Certificate authority file provided by the user
private String certParameter; // Path to certificate provided by user
private String distinguishedName; // Certificate distinguished name provided by the user
private String commonName; // Common name extracted from distinguishedName
private String connectingUserName; // User-name used to establish connection
private String specifiedUserName; // -username- (add/drop) operation is being performed on
private boolean adminPrivilegeRequested; // true is attempting to give user admin privileges
private boolean forceShutdown; // Whether or not to force a shutdown (--force)
private String loadLibraryVar; // Environment variable pointing to postgres shared libraries
private String loadLibraryValue; // Directory containing shared libraries within postgres software
private int port; // Port over which to connect to postgres server, (-1 indicates default port is used)
private int localAuthentication; // Type of authentication required for local connections
private int hostAuthentication; // Type of authentication for remote connections
private boolean authConfigPresent; // True if the [auth=..] option or the [--noLocalAuth] is present
private File passwordFile; // File containing newly established password
private char[] adminPasswordData; // Password data being sent to postgres server for authentication
// Database connection that can be persisted so we don't need to recreate one
// for every call.
private Connection localConnection;
/**
* Exception triggered by missing, unknown, or improperly formatted command-line arguments
* Constructor for launching from the console
*/
public static class ArgumentException extends Exception {
public ArgumentException(String message) {
super(message);
}
public BSimControlLaunchable() {
}
private void clearParams() {
dataDirectory = null;
postgresRoot = null;
postgresControl = null;
certAuthorityFile = null;
certParameter = null;
distinguishedName = null;
commonName = null;
connectingUserName = null;
specifiedUserName = null;
adminPrivilegeRequested = false;
forceShutdown = false;
loadLibraryVar = null;
loadLibraryValue = null;
port = -1;
localAuthentication = AUTHENTICATION_NONE;
hostAuthentication = AUTHENTICATION_NONE;
authConfigPresent = false;
passwordFile = null;
adminPasswordData = null;
}
/**
* Class for processing standard output or standard error for processes invoked by BSimControl
* The streams can be optionally suppressed or dumped to System.out
* Read required parameters followed by optional parameters
* @param params is the original array of command line parameters
*/
private class IOThread extends Thread {
private BufferedReader shellOutput; // Reader for the particular output stream
private boolean suppressOutput; // If false, shell output is printed on the console
private String readCommandLine(String[] params) throws IllegalArgumentException, IOException {
public IOThread(InputStream input, boolean suppressOut) {
shellOutput = new BufferedReader(new InputStreamReader(input));
suppressOutput = suppressOut;
int slot = 0;
checkRequiredParam(params, slot, "command");
String command = params[slot++];
switch (command) {
case COMMAND_START:
scanDataDirectory(params, slot++);
break;
case COMMAND_STOP:
scanDataDirectory(params, slot++);
break;
case COMMAND_ADDUSER:
scanDataDirectory(params, slot++);
scanUsername(params, slot++);
break;
case COMMAND_DROPUSER:
scanDataDirectory(params, slot++);
scanUsername(params, slot++);
break;
case COMMAND_RESET_PASSWORD:
scanUsername(params, slot++);
break;
case COMMAND_CHANGEAUTH:
scanDataDirectory(params, slot++);
break;
case COMMAND_CHANGE_PRIVILEGE:
scanUsername(params, slot++);
scanPrivilege(params, slot++);
break;
default:
throw new IllegalArgumentException("Unknown command: " + command);
}
@Override
public void run() {
String line = null;
try {
while ((line = shellOutput.readLine()) != null) {
if (!suppressOutput) {
System.out.println(line);
}
readOptions(command, params, slot);
return command;
}
/**
* Read in any optional parameters, strip them from the parameter stream
* @param command command name
* @param params is the original array of command line parameters
* @param discard number of params already consumed
*/
private void readOptions(String command, String[] params, int discard) {
boolean sawNoLocalAuth = false;
Set<String> allowedParams = ALLOWED_OPTION_MAP.get(command);
if (allowedParams == null) {
throw new IllegalArgumentException("Unsupported command: " + command);
}
for (int i = discard; i < params.length; ++i) {
String optionName = params[i];
String value = null;
if (optionName.startsWith("-")) {
// although not prefered, allow option value to be specified as --option=value
int ix = optionName.indexOf("=");
if (ix > 1) {
value = optionName.substring(ix + 1);
optionName = optionName.substring(0, ix);
}
}
catch (Exception e) {
// DO NOT USE LOGGING HERE (class loader)
System.err.println("Unexpected Exception: " + e.getMessage());
e.printStackTrace(System.err);
String option = optionName;
if (optionName.startsWith("-") && !optionName.startsWith("--")) {
option = SHORTCUT_OPTION_MAP.get(optionName); // map option to -- long form
if (option == null) {
throw new IllegalArgumentException("Unsupported option use: " + optionName);
}
}
if (!option.startsWith("--")) {
throw new IllegalArgumentException("Unexpected argument: " + option);
}
if (!GLOBAL_OPTIONS.contains(option) && !allowedParams.contains(option)) {
throw new IllegalArgumentException("Unsupported option use: " + optionName);
}
if (!VALUE_OPTIONS.contains(option)) {
// option without value arg
if (value != null) {
throw new IllegalArgumentException(
"Unsupported option specification: " + optionName + "=");
}
}
else if (StringUtils.isBlank(value)) {
// consume next param as option value
if (++i == params.length) {
throw new IllegalArgumentException("Missing option value: " + optionName);
}
value = params[i];
}
switch (option) {
case PORT_OPTION:
port = parsePositiveIntegerOption(optionName, value);
break;
case USER_OPTION:
connectingUserName = value;
break;
case CERT_OPTION:
certParameter = value;
break;
case CAFILE_OPTION:
certAuthorityFile = new File(value);
break;
case AUTH_OPTION:
authConfigPresent = true;
String type = value;
if (type.equals("pki")) {
hostAuthentication = AUTHENTICATION_PKI;
localAuthentication = AUTHENTICATION_PKI;
}
else if (type.equals("password")) {
hostAuthentication = AUTHENTICATION_PASSWORD;
localAuthentication = AUTHENTICATION_PASSWORD;
}
else if (type.equals("trust") || type.equals("none")) {
hostAuthentication = AUTHENTICATION_NONE;
localAuthentication = AUTHENTICATION_NONE;
}
else {
throw new IllegalArgumentException("Unknown authentication method: " +
type + " : options are trust, password or pki");
}
break;
case DN_OPTION:
distinguishedName = value;
validateDistinguishedName();
break;
case NO_LOCAL_AUTH_OPTION:
sawNoLocalAuth = true;
break;
case FORCE_OPTION:
forceShutdown = true;
break;
default:
throw new AssertionError("Missing option handling: " + option);
}
}
if (sawNoLocalAuth) { // Turn off authentication for local connections
authConfigPresent = true;
localAuthentication = AUTHENTICATION_NONE;
}
if (connectingUserName == null) {
connectingUserName = ClientUtil.getUserName();
}
}
public BSimControlLaunchable() {
// Constructor for main launcher
private void checkRequiredParam(String[] params, int index, String name) {
if (params.length <= index) {
throw new IllegalArgumentException("Missing required parameter: " + name);
}
String p = params[index];
if (p.startsWith("--")) {
throw new IllegalArgumentException(
"Missing required parameter (" + name + ") before specified option: " + p);
}
}
private int parsePositiveIntegerOption(String option, String optionValue) {
try {
int value = Integer.valueOf(optionValue);
if (value < 0) {
throw new IllegalArgumentException("Negative value not permitted for " + option);
}
return value;
}
catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid integer value specified for " + option);
}
}
/**
@ -179,9 +398,12 @@ public class BSimControlLaunchable implements GhidraLaunchable {
* Parse the -distinguishedName- String, verifying it is has the correct format for a
* X509 certificate distinguished name. Try to extract the common name portion of the
* distinguished name and assign it to -commonName-
* @throws ArgumentException if the distinguished name is improperly formatted or the common name is missing
* @throws IllegalArgumentException if the distinguished name is improperly formatted or the common name is missing
*/
private void validateDistinguishedName() throws ArgumentException {
private void validateDistinguishedName() throws IllegalArgumentException {
if (distinguishedName == null) {
return;
}
commonName = null;
try {
LdapName ldapName = new LdapName(distinguishedName);
@ -192,11 +414,11 @@ public class BSimControlLaunchable implements GhidraLaunchable {
}
}
if (commonName == null) {
throw new ArgumentException("Missing common name attribute");
throw new IllegalArgumentException("Missing common name attribute");
}
}
catch (Exception e) {
throw new ArgumentException("Improperly formatted distinguished name");
throw new IllegalArgumentException("Improperly formatted distinguished name");
}
}
@ -297,6 +519,10 @@ public class BSimControlLaunchable implements GhidraLaunchable {
* @throws IOException if the password file cannot be deleted
*/
private void cleanupPasswordData() throws IOException {
clearPasswordData(adminPasswordData);
adminPasswordData = null;
if (passwordFile != null) {
if (!passwordFile.delete()) {
throw new IOException(
@ -304,8 +530,6 @@ public class BSimControlLaunchable implements GhidraLaunchable {
}
passwordFile = null;
}
clearPasswordData(adminPasswordData);
adminPasswordData = null;
}
/**
@ -367,18 +591,6 @@ public class BSimControlLaunchable implements GhidraLaunchable {
}
}
/**
* Initialize enough of Ghidra to allow navigation of configuration files and to allow SSL connections
* @throws IOException if the headless authenticator cannot be initialized
* @throws ClassNotFoundException if the postgres driver class cannot be found
*/
private void initializeApplication() throws IOException, ClassNotFoundException {
if (layout != null) {
// Initialize application environment consistent with bsim command
BSimLaunchable.initializeApplication(layout, 0, connectingUserName, certParameter);
}
}
/**
* Create a local connection to a postgres server. A full SSL connection is created using
* Ghidra's infrastructure. If the initial connection fails because password authentication
@ -678,7 +890,7 @@ public class BSimControlLaunchable implements GhidraLaunchable {
else if (hostAuthentication == AUTHENTICATION_PKI) {
if (commonName == null) {
throw new GeneralSecurityException(
"Distinguished name required for " + connectingUserName + " (dn=\"..\")");
"Distinguished name option (--dn) required for " + connectingUserName);
}
checkCertAuthorityFile();
}
@ -717,19 +929,19 @@ public class BSimControlLaunchable implements GhidraLaunchable {
/**
* Scan the PostgreSQL data directory from the command-line
* Make sure the directory exists and establish the File object -dataDirectory-
* @param params are the command-line options
* @param slot is the position to retrieve the data directory
* @throws ArgumentException if the data directory is invalid
* @param params are the command-line arguments
* @param slot is the position to retrieve the data directory argument
* @throws IllegalArgumentException if the data directory is invalid
* @throws IOException if the canonical file cannot be retrieved
*/
private void scanDataDirectory(String[] params, int slot)
throws ArgumentException, IOException {
throws IllegalArgumentException, IOException {
if (params.length <= slot) {
throw new ArgumentException("Missing data directory");
throw new IllegalArgumentException("Missing data directory");
}
dataDirectory = new File(params[slot]);
if (!dataDirectory.isDirectory()) {
throw new ArgumentException(
throw new IllegalArgumentException(
"Data directory " + dataDirectory.getAbsolutePath() + " does not exist");
}
dataDirectory = dataDirectory.getCanonicalFile();
@ -737,13 +949,13 @@ public class BSimControlLaunchable implements GhidraLaunchable {
/**
* Scan the username from the command-line
* @param params are the command-line options
* @param slot is the position to retrieve the username
* @throws ArgumentException if the user name is not in the given params
* @param params are the command-line arguments
* @param slot is the position to retrieve the username argument
* @throws IllegalArgumentException if the user name is not in the given params
*/
private void scanUsername(String[] params, int slot) throws ArgumentException {
private void scanUsername(String[] params, int slot) throws IllegalArgumentException {
if (params.length <= slot) {
throw new ArgumentException("Missing username");
throw new IllegalArgumentException("Missing username");
}
specifiedUserName = params[slot];
}
@ -751,13 +963,13 @@ public class BSimControlLaunchable implements GhidraLaunchable {
/**
* Scan command-line for a particular privilege level. Administrator privileges are
* requested with the exact String "admin", anything is a request for a read-only user
* @param params are the command-line options
* @param slot is the position to retrieve the user name
* @throws ArgumentException the privilege parameter is missing
* @param params are the command-line arguments
* @param slot is the position to retrieve the user name argument
* @throws IllegalArgumentException the privilege parameter is missing
*/
private void scanPrivilege(String[] params, int slot) throws ArgumentException {
private void scanPrivilege(String[] params, int slot) throws IllegalArgumentException {
if (params.length <= slot) {
throw new ArgumentException("Missing desired privilege (admin or user)");
throw new IllegalArgumentException("Missing desired privilege (admin or user)");
}
if (params[slot].equals("admin")) {
adminPrivilegeRequested = true;
@ -766,7 +978,7 @@ public class BSimControlLaunchable implements GhidraLaunchable {
adminPrivilegeRequested = false;
}
else {
throw new ArgumentException("Expecting privilege option (admin or user)");
throw new IllegalArgumentException("Expecting privilege option (admin or user)");
}
}
@ -789,7 +1001,7 @@ public class BSimControlLaunchable implements GhidraLaunchable {
if (localAuthentication == AUTHENTICATION_PKI && certParameter == null) {
throw new GeneralSecurityException(
"Path to certificate necessary to start server (cert=/path/to/cert)");
"Path to certificate necessary to start server (--cert /path/to/cert)");
}
File logFile = new File(dataDirectory, "logfile");
List<String> command = new ArrayList<String>();
@ -883,58 +1095,6 @@ public class BSimControlLaunchable implements GhidraLaunchable {
FileUtilities.copyFile(copyFile, identFile, false, null);
}
/**
* Returns a list of all users registered with the BSim server.
*
* Note: This will return all users minus those created by Postgres (those that
* start with 'pg_'.
*
* @param dataDirectory the location of the Postgres database files
* @return map of database users and their admin status
* @throws Exception if there's a problem initializing the Application or searching for Postgres
*/
public Map<String, Boolean> getUserRolesCommand(String dataDirectory) throws Exception {
String[] params = { dataDirectory };
scanDataDirectory(params, 0);
initializeApplication();
discoverPostgresInstall();
if (connectingUserName == null) {
connectingUserName = ClientUtil.getUserName();
}
adminPasswordData = null;
localConnection = getOrCreateLocalConnection();
StringBuilder buffer = new StringBuilder();
buffer.append("SELECT rolname, rolsuper from pg_roles");
try (Statement st = localConnection.createStatement()) {
Map<String, Boolean> userToAdminMap = new HashMap<>();
try (ResultSet rs = st.executeQuery(buffer.toString())) {
while (rs.next()) {
String user = rs.getString(1);
if (user.startsWith("pg_")) { // default postgres role - ignore
continue;
}
Boolean isAdmin = rs.getBoolean(2);
userToAdminMap.put(user, isAdmin);
}
return userToAdminMap;
}
}
catch (SQLException e) {
Msg.error(this, "Error retrieving user roles from the Postgres database", e);
}
finally {
localConnection.close();
}
return Collections.emptyMap();
}
/**
* Add a new user to the currently running server on the local host.
* A connection is established, using the local interface, and the "CREATE ROLE" command
@ -1073,7 +1233,7 @@ public class BSimControlLaunchable implements GhidraLaunchable {
* @throws SAXException if the {@link #tuneConfig(File, File, File, File, File)} call fails
* @throws GeneralSecurityException if there is no Distinguished Name supplied
*/
private void resetCommand()
private void changeAuthCommand()
throws IOException, InterruptedException, SAXException, GeneralSecurityException {
discoverPostgresInstall();
File configFile = new File(dataDirectory, POSTGRES_CONFIGFILE);
@ -1195,7 +1355,7 @@ public class BSimControlLaunchable implements GhidraLaunchable {
}
}
private void privilegeCommand() throws Exception {
private void changePrivilegeCommand() throws Exception {
localConnection = getOrCreateLocalConnection();
try {
if (adminPrivilegeRequested) {
@ -1214,231 +1374,158 @@ public class BSimControlLaunchable implements GhidraLaunchable {
}
}
/**
* Parse the command-line. First argument is always a command, which may
* require additional arguments. Additional optional arguments may follow
* @param params is the array of command-line arguments
* @throws ArgumentException if the data directory cannot be scanned or the authentication method is invalid
* @throws IOException if the data directory cannot be scanned
*/
private void readCommandLine(String[] params) throws ArgumentException, IOException {
String command = params[0];
int slot = 1;
if (command.equals(START_COMMAND)) {
scanDataDirectory(params, slot);
slot += 1;
}
else if (command.equals(STOP_COMMAND)) {
scanDataDirectory(params, slot);
slot += 1;
}
else if (command.equals(ADDUSER_COMMAND)) {
scanDataDirectory(params, slot);
slot += 1;
scanUsername(params, slot);
slot += 1;
}
else if (command.equals(DROPUSER_COMMAND)) {
scanDataDirectory(params, slot);
slot += 1;
scanUsername(params, slot);
slot += 1;
}
else if (command.equals(PASSWORD_COMMAND)) {
scanUsername(params, slot);
slot += 1;
}
else if (command.equals(RESET_COMMAND)) {
scanDataDirectory(params, slot);
slot += 1;
}
else if (command.equals(PRIVILEGE_COMMAND)) {
scanUsername(params, slot);
slot += 1;
scanPrivilege(params, slot);
slot += 1;
}
else {
throw new ArgumentException("Unknown command: " + command);
}
// Scan for optional arguments
boolean sawNoLocalAuth = false;
for (int i = slot; i < params.length; ++i) {
String option = params[i];
if (option.startsWith(PORT_OPTION)) {
port = Integer.parseInt(option.substring(PORT_OPTION.length()));
}
else if (option.startsWith(CAFILE_OPTION)) {
certAuthorityFile = new File(option.substring(CAFILE_OPTION.length()));
}
else if (option.startsWith(AUTH_OPTION)) {
authConfigPresent = true;
String type = option.substring(AUTH_OPTION.length());
if (type.equals("pki")) {
hostAuthentication = AUTHENTICATION_PKI;
localAuthentication = AUTHENTICATION_PKI;
}
else if (type.equals("password")) {
hostAuthentication = AUTHENTICATION_PASSWORD;
localAuthentication = AUTHENTICATION_PASSWORD;
}
else if (type.equals("trust") || type.equals("none")) {
hostAuthentication = AUTHENTICATION_NONE;
localAuthentication = AUTHENTICATION_NONE;
}
else {
throw new ArgumentException(
"Unknown authentication method: " + type + " : options are trust, pki");
}
}
else if (option.startsWith(DN_OPTION)) {
distinguishedName = option.substring(DN_OPTION.length());
validateDistinguishedName();
}
else if (option.startsWith(CERT_OPTION)) {
certParameter = option.substring(CERT_OPTION.length());
}
else if (option.startsWith(NO_LOCAL_AUTH_OPTION)) {
sawNoLocalAuth = true;
}
else if (option.equals(FORCE_OPTION)) {
forceShutdown = true;
}
else if (option.startsWith(USER_OPTION)) {
connectingUserName = option.substring(USER_OPTION.length());
}
else {
throw new ArgumentException("Unknown option: " + option);
}
}
if (sawNoLocalAuth) { // Turn off authentication for local connections
authConfigPresent = true;
localAuthentication = AUTHENTICATION_NONE;
}
if (connectingUserName == null) {
connectingUserName = ClientUtil.getUserName();
}
}
/**
* Runs the command specified by the given set of params.
*
* @param params the command parameters
* @param monitor the task monitor
* @throws Exception if there is a problem executing the command
*/
public void run(String[] params, TaskMonitor monitor) throws Exception {
String command = params[0];
try {
readCommandLine(params);
initializeApplication();
if (command.equals(START_COMMAND)) {
startCommand();
}
else if (command.equals(STOP_COMMAND)) {
stopCommand();
}
else if (command.equals(ADDUSER_COMMAND)) {
addUserCommand();
}
else if (command.equals(DROPUSER_COMMAND)) {
dropUserCommand();
}
else if (command.equals(RESET_COMMAND)) {
resetCommand();
}
else if (command.equals(PASSWORD_COMMAND)) {
passwordCommand();
}
else if (command.equals(PRIVILEGE_COMMAND)) {
privilegeCommand();
}
}
catch (SAXException e1) {
System.err.println("Error in server configuation data");
System.err.println(e1.getMessage());
throw e1;
}
catch (IOException e1) {
System.err.println("Error configuring PostgreSQL for BSim");
System.err.println(e1.getMessage());
throw e1;
}
catch (InterruptedException e) {
System.err.println("Command was interrupted");
System.err.println(e.getMessage());
throw e;
}
catch (SQLException e) {
System.err.println("Error connecting to the database");
System.err.println(e.getMessage());
throw e;
}
catch (GeneralSecurityException e) {
System.err.println("Error establishing server certificate");
System.err.println(e.getMessage());
throw e;
}
catch (ArgumentException e) {
System.err.println("Error in command line arguments");
System.err.println(e.getMessage());
throw e;
}
catch (ClassNotFoundException e) {
System.err.println("Could not find PostgreSQL JDBC driver");
System.err.println(e.getMessage());
throw e;
}
try {
cleanupPasswordData();
}
catch (IOException e) {
e.printStackTrace();
}
}
/**
* Runs the command specified by the given set of params.
*
* @param params the command parameters
* @throws Exception if there is a problem executing the command
* @param params the parameters specifying the command
* @throws IllegalArgumentException if invalid params have been specified
* @throws Exception if there's an error during the operation
* @throws CancelledException if processing is cancelled
*/
public void run(String[] params) throws Exception {
run(params, TaskMonitor.DUMMY);
try {
clearParams();
String command = readCommandLine(params);
initializeApplication();
switch (command) {
case COMMAND_START:
startCommand();
break;
case COMMAND_STOP:
stopCommand();
break;
case COMMAND_ADDUSER:
addUserCommand();
break;
case COMMAND_DROPUSER:
dropUserCommand();
break;
case COMMAND_CHANGEAUTH:
changeAuthCommand();
break;
case COMMAND_RESET_PASSWORD:
passwordCommand();
break;
case COMMAND_CHANGE_PRIVILEGE:
changePrivilegeCommand();
break;
default:
throw new IllegalArgumentException("Unknown command: " + command);
}
}
finally {
try {
cleanupPasswordData();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public void launch(GhidraApplicationLayout ghidraLayout, String[] params) {
if (params.length <= 1) {
//@formatter:off
System.err.println("USAGE:");
System.err.println(" bsim_ctl start </datadir-path> [auth=pki|password|trust] [--noLocalAuth] [cafile=</cacert-path>] [dn=\"..\"]");
System.err.println(" stop </datadir-path> [--force]");
System.err.println(" adduser </datadir-path> <username> [dn=\"..\"]");
System.err.println(" dropuser </datadir-path> <username>");
System.err.println(" changeauth </datadir-path> [auth=pki|password|trust] [--noLocalAuth] [cafile=</cacert-path>]");
System.err.println(" resetpassword <username>");
System.err.println(" changeprivilege <username> admin|user");
System.err.println("USAGE: bsim_ctl [command] required-args... [OPTIONS...}\n");
System.err.println(" start </datadir-path> [--auth|-a pki|password|trust] [--noLocalAuth] [--cafile \"</cacert-path>\"] [--dn \"<distinguished-name>\"]");
System.err.println(" stop </datadir-path> [--force]");
System.err.println(" adduser </datadir-path> <username> [--dn \"<distinguished-name>\"]");
System.err.println(" dropuser </datadir-path> <username>");
System.err.println(" changeauth </datadir-path> [--auth|-a pki|password|trust] [--noLocalAuth] [--cafile \"</cacert-path>\"]");
System.err.println(" resetpassword <username>");
System.err.println(" changeprivilege <username> admin|user");
System.err.println();
System.err.println("Global options:");
System.err.println(" port=<portnum>");
System.err.println(" user=<username>");
System.err.println(" cert=</certfile-path>");
System.err.println(" --port|-p <portnum>");
System.err.println(" --user|-u <username>");
System.err.println(" --cert </certfile-path>");
System.err.println();
System.err.println("NOTE: Options with values may also be specified using the form: --option=value\n");
System.err.println();
//@formatter:on
return;
}
layout = ghidraLayout; // Save layout for when we need to initialize application
boolean success = false;
try {
run(params);
success = true;
}
catch (RuntimeException e) {
e.printStackTrace();
System.exit(1);
catch (SAXException e1) {
System.err.println("Error in server configuation data");
System.err.println(e1.getMessage());
}
catch (InterruptedException e) {
System.err.println("Command was interrupted");
System.err.println(e.getMessage());
}
catch (SQLException e) {
System.err.println("Error connecting to the database");
System.err.println(e.getMessage());
}
catch (GeneralSecurityException e) {
System.err.println("Error establishing server certificate");
System.err.println(e.getMessage());
}
catch (IllegalArgumentException e) {
System.err.println("Error in command line arguments");
System.err.println(e.getMessage());
}
catch (Exception e) {
System.err.println("Unexpected error");
e.printStackTrace();
}
if (!success) {
System.exit(1);
}
}
/**
* Initialize enough of Ghidra to allow navigation of configuration files and to allow SSL connections
* @throws IOException if the headless authenticator cannot be initialized
* @throws ClassNotFoundException if the postgres driver class cannot be found
*/
private void initializeApplication() throws IOException, ClassNotFoundException {
if (layout != null) {
// Initialize application environment consistent with bsim command
BSimLaunchable.initializeApplication(layout, 0, connectingUserName, certParameter);
}
}
/**
* Class for processing standard output or standard error for processes invoked by BSimControl
* The streams can be optionally suppressed or dumped to System.out
*/
private class IOThread extends Thread {
private BufferedReader shellOutput; // Reader for the particular output stream
private boolean suppressOutput; // If false, shell output is printed on the console
public IOThread(InputStream input, boolean suppressOut) {
shellOutput = new BufferedReader(new InputStreamReader(input));
suppressOutput = suppressOut;
}
@Override
public void run() {
String line = null;
try {
while ((line = shellOutput.readLine()) != null) {
if (!suppressOutput) {
System.out.println(line);
}
}
}
catch (Exception e) {
// DO NOT USE LOGGING HERE (class loader)
System.err.println("Unexpected Exception: " + e.getMessage());
e.printStackTrace(System.err);
}
}
}
}

View File

@ -245,7 +245,7 @@ public interface FunctionDatabase extends AutoCloseable {
public static boolean checkSettingsForInsert(DescriptionManager manage,
DatabaseInformation info) throws LSHException, DatabaseNonFatalException {
if (manage.numFunctions() == 0) {
throw new DatabaseNonFatalException("ls ~/junk" + "");
throw new DatabaseNonFatalException("Empty signature file");
}
int res = info.checkSignatureSettings(manage.getMajorVersion(), manage.getMinorVersion(),
manage.getSettings());

View File

@ -20,6 +20,7 @@ import java.io.IOException;
import java.net.*;
import java.util.*;
import org.apache.commons.lang3.StringUtils;
import org.xml.sax.SAXException;
import ghidra.GhidraApplicationLayout;
@ -77,27 +78,29 @@ public class BSimLaunchable implements GhidraLaunchable {
private static Set<String> COMMANDS_WITH_REPO_ACCESS =
Set.of(COMMAND_GENERATE_SIGS, COMMAND_GENERATE_UPDATES);
/**
* Constants for the option parameters that can be set in the various commands.
*/
private static final String BSIM_URL_OPTION = "bsim=";
private static final String GHIDRA_URL_OPTION = "ghidra=";
private static final String NAME_OPTION = "name=";
private static final String OWNER_OPTION = "owner=";
private static final String DESCRIPTION_OPTION = "description=";
private static final String OVERRIDE_OPTION = "override=";
private static final String CONFIG_OPTION = "config=";
private static final String MD5_OPTION = "md5=";
private static final String MAX_FUNC_OPTION = "maxfunc=";
private static final String FILTER_OPTION = "filter=";
private static final String ARCH_OPTION = "arch=";
private static final String COMPILER_OPTION = "compiler=";
private static final String LIMIT_OPTION = "limit=";
private static final String SORT_COL_OPTION = "sortcol=";
// Options that require a value argument
private static final String BSIM_URL_OPTION = "--bsim";
private static final String NAME_OPTION = "--name";
private static final String OWNER_OPTION = "--owner";
private static final String DESCRIPTION_OPTION = "--description";
private static final String OVERRIDE_OPTION = "--override";
private static final String CONFIG_OPTION = "--config";
private static final String MD5_OPTION = "--md5";
private static final String MAX_FUNC_OPTION = "--maxfunc";
private static final String ARCH_OPTION = "--arch";
private static final String COMPILER_OPTION = "--compiler";
private static final String LIMIT_OPTION = "--limit";
private static final String SORT_COL_OPTION = "--sortcol";
// Global options
private static final String USER_OPTION = "user=";
private static final String CERT_OPTION = "cert=";
// Global options that require a value argument
private static final String USER_OPTION = "--user";
private static final String CERT_OPTION = "--cert";
// Define set of options that require a second value argument
private static final Set<String> VALUE_OPTIONS =
Set.of(USER_OPTION, CERT_OPTION, BSIM_URL_OPTION, NAME_OPTION, OWNER_OPTION,
DESCRIPTION_OPTION, OVERRIDE_OPTION, CONFIG_OPTION, MD5_OPTION, MAX_FUNC_OPTION,
ARCH_OPTION, COMPILER_OPTION, LIMIT_OPTION, SORT_COL_OPTION);
private static final Set<String> GLOBAL_OPTIONS = Set.of(CERT_OPTION, USER_OPTION);
@ -111,12 +114,30 @@ public class BSimLaunchable implements GhidraLaunchable {
private static final String CALL_GRAPH_OPTION = "--callgraph";
private static final String PRINT_JUST_EXE_OPTION = "--printjustexe";
private static final Map<String, String> SHORTCUT_OPTION_MAP = new HashMap<>();
static {
SHORTCUT_OPTION_MAP.put("-a", ARCH_OPTION);
SHORTCUT_OPTION_MAP.put("-b", BSIM_URL_OPTION);
SHORTCUT_OPTION_MAP.put("-c", CONFIG_OPTION);
SHORTCUT_OPTION_MAP.put("-d", DESCRIPTION_OPTION);
SHORTCUT_OPTION_MAP.put("-l", LIMIT_OPTION);
SHORTCUT_OPTION_MAP.put("-m", MD5_OPTION);
SHORTCUT_OPTION_MAP.put("-n", NAME_OPTION);
SHORTCUT_OPTION_MAP.put("-o", OWNER_OPTION);
SHORTCUT_OPTION_MAP.put("-s", SORT_COL_OPTION);
SHORTCUT_OPTION_MAP.put("-u", USER_OPTION);
//SHORTCUT_OPTION_MAP.put("", OVERRIDE_OPTION);
//SHORTCUT_OPTION_MAP.put("", MAX_FUNC_OPTION);
//SHORTCUT_OPTION_MAP.put("", COMPILER_OPTION);
//SHORTCUT_OPTION_MAP.put("", CERT_OPTION);
}
//@formatter:off
// Populate ALLOWED_OPTION_MAP for each command
private static final Set<String> CREATE_DATABASE_OPTIONS =
Set.of(NAME_OPTION, OWNER_OPTION, DESCRIPTION_OPTION, NO_CALLGRAPH_OPTION);
private static final Set<String> COMMIT_SIGS_OPTIONS =
Set.of(OVERRIDE_OPTION, GHIDRA_URL_OPTION); // url requires override param
Set.of(OVERRIDE_OPTION, MD5_OPTION); // url requires override param
private static final Set<String> COMMIT_UPDATES_OPTIONS = Set.of();
private static final Set<String> DELETE_OPTIONS =
Set.of(MD5_OPTION, NAME_OPTION, ARCH_OPTION, COMPILER_OPTION); // one or more params required
@ -164,23 +185,7 @@ public class BSimLaunchable implements GhidraLaunchable {
private URL ghidraURL;
private URL bsimURL;
private String bsimURLOption; // Command-line option: bsim=..
private String ghidraURLOption; // Command-line option: ghidra=..
private String nameOption; // Command-line option: name=..
private String ownerOption; // Command-line option: owner=..
private String archOption; // Command-line option: arch=..
private String compOption; // Command-line option: compiler=..
private String descOption; // Command-line option: description=
private String filterOption; // Command-line option: filter=
private String configOption; // Command-line option: config=..
private String md5Option; // Command-line option: md5=..
private Integer maxFunc; // Command-line option: maxfunc=..
private String certOption; // Command-line option: cert=..
private String connectingUserName; // Command-line option: user=..
private Integer limitOption; // Command-line option: limit=..
private String sortColumn; // Command-line option: sortcol=..
private boolean overrideOption; // Command-line option: override=
private Map<String, String> optionValueMap = new HashMap<>();
private Set<String> booleanOptions = new HashSet<>();
private GhidraApplicationLayout layout;
@ -199,22 +204,8 @@ public class BSimLaunchable implements GhidraLaunchable {
private void clearParams() {
ghidraURL = null;
bsimURL = null;
bsimURLOption = null;
ghidraURLOption = null;
connectingUserName = null;
nameOption = null;
ownerOption = null;
archOption = null;
compOption = null;
descOption = null;
filterOption = null;
configOption = null;
md5Option = null;
certOption = null;
limitOption = null;
sortColumn = null;
overrideOption = false;
booleanOptions.clear();
optionValueMap.clear();
}
private BulkSignatures getBulkSignatures()
@ -223,6 +214,7 @@ public class BSimLaunchable implements GhidraLaunchable {
if (bsimURL != null) {
serverInfo = new BSimServerInfo(bsimURL);
}
String connectingUserName = optionValueMap.get(USER_OPTION);
return new BulkSignatures(serverInfo, connectingUserName);
}
@ -281,6 +273,8 @@ public class BSimLaunchable implements GhidraLaunchable {
*/
private List<String> readOptions(String command, String[] params, int discard) {
boolean sawOptions = false;
Set<String> allowedParams = ALLOWED_OPTION_MAP.get(command);
if (allowedParams == null) {
throw new IllegalArgumentException("Unsupported command: " + command);
@ -288,101 +282,61 @@ public class BSimLaunchable implements GhidraLaunchable {
List<String> subParams = new ArrayList<String>();
for (int i = discard; i < params.length; ++i) {
String option = params[i];
String optionName = params[i];
String value = null;
int ix = option.indexOf('=');
if (ix > 0) {
String checkOption = option.substring(0, ix + 1); // include '=' in option name
if (!GLOBAL_OPTIONS.contains(checkOption) && !allowedParams.contains(checkOption)) {
throw new IllegalArgumentException("Unsupported option use: " + checkOption);
if (optionName.startsWith("-")) {
// although not prefered, allow option value to be specified as --option=value
int ix = optionName.indexOf("=");
if (ix > 1) {
value = optionName.substring(ix + 1);
optionName = optionName.substring(0, ix);
}
}
else if (option.startsWith("--")) {
if (!GLOBAL_OPTIONS.contains(option) && !allowedParams.contains(option)) {
throw new IllegalArgumentException("Unsupported option use: " + option);
String option = optionName;
if (optionName.startsWith("-") && !optionName.startsWith("--")) {
option = SHORTCUT_OPTION_MAP.get(optionName); // map option to -- long form
if (option == null) {
throw new IllegalArgumentException("Unsupported option use: " + optionName);
}
booleanOptions.add(option);
}
if (!option.startsWith("--")) {
if (sawOptions) {
throw new IllegalArgumentException("Unexpected argument: " + option);
}
subParams.add(params[i]);
continue;
}
if (option.startsWith(BSIM_URL_OPTION)) {
bsimURLOption = option.substring(BSIM_URL_OPTION.length());
sawOptions = true;
if (!GLOBAL_OPTIONS.contains(option) && !allowedParams.contains(option)) {
throw new IllegalArgumentException("Unsupported option use: " + optionName);
}
else if (option.startsWith(GHIDRA_URL_OPTION)) {
ghidraURLOption = option.substring(GHIDRA_URL_OPTION.length());
}
else if (option.startsWith(NAME_OPTION)) {
nameOption = option.substring(NAME_OPTION.length());
}
else if (option.startsWith(OWNER_OPTION)) {
ownerOption = option.substring(OWNER_OPTION.length());
}
else if (option.startsWith(DESCRIPTION_OPTION)) {
descOption = option.substring(DESCRIPTION_OPTION.length());
}
else if (option.startsWith(OVERRIDE_OPTION)) {
overrideOption = true;
ghidraURLOption = option.substring(OVERRIDE_OPTION.length());
}
else if (option.startsWith(CONFIG_OPTION)) {
configOption = option.substring(CONFIG_OPTION.length());
}
else if (option.startsWith(MD5_OPTION)) {
md5Option = option.substring(MD5_OPTION.length());
}
else if (option.startsWith(MAX_FUNC_OPTION)) {
String val = option.substring(MAX_FUNC_OPTION.length());
try {
maxFunc = Integer.valueOf(val);
if (maxFunc < 0) {
throw new IllegalArgumentException(
"Negative value not permitted for maxfunc");
}
}
catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid decimal value for maxfunc: " + val);
if (!VALUE_OPTIONS.contains(option)) {
// consume option without value arg as a boolean option
if (value != null) {
throw new IllegalArgumentException(
"Unsupported option specification: " + optionName + "=");
}
booleanOptions.add(option);
}
else if (option.startsWith(FILTER_OPTION)) {
filterOption = option.substring(FILTER_OPTION.length());
}
else if (option.startsWith(CERT_OPTION)) { // global option
certOption = option.substring(CERT_OPTION.length());
}
else if (option.startsWith(USER_OPTION)) { // global option
connectingUserName = option.substring(USER_OPTION.length());
}
else if (option.startsWith(ARCH_OPTION)) {
archOption = option.substring(ARCH_OPTION.length());
}
else if (option.startsWith(COMPILER_OPTION)) {
compOption = option.substring(COMPILER_OPTION.length());
}
else if (option.startsWith(LIMIT_OPTION)) {
String val = option.substring(LIMIT_OPTION.length());
try {
limitOption = Integer.valueOf(val);
if (limitOption < 0) {
throw new IllegalArgumentException(
"Negative value not permitted for limit");
}
}
catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid decimal value for limit: " + val);
}
}
else if (option.startsWith(SORT_COL_OPTION)) {
sortColumn = option.substring(SORT_COL_OPTION.length());
}
else if (params[i].startsWith("--") || params[i].contains("=")) {
throw new IllegalArgumentException("Unknown option: " + params[i]);
else if (!StringUtils.isBlank(value)) {
optionValueMap.put(option, value);
}
else {
subParams.add(params[i]);
// consume next param as option value
if (++i == params.length) {
throw new IllegalArgumentException("Missing option value: " + optionName);
}
optionValueMap.put(option, params[i]);
}
}
String connectingUserName = optionValueMap.get(USER_OPTION);
if (connectingUserName == null) {
connectingUserName = ClientUtil.getUserName();
connectingUserName = optionValueMap.put(USER_OPTION, ClientUtil.getUserName());
}
return subParams;
}
@ -398,6 +352,23 @@ public class BSimLaunchable implements GhidraLaunchable {
}
}
private Integer parsePositiveIntegerOption(String option) {
String optionValue = optionValueMap.get(option);
if (optionValue == null) {
return null;
}
try {
int value = Integer.valueOf(optionValue);
if (value < 0) {
throw new IllegalArgumentException("Negative value not permitted for " + option);
}
return value;
}
catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid integer value specified for " + option);
}
}
/**
* Runs the command specified by the given set of params.
*
@ -409,6 +380,8 @@ public class BSimLaunchable implements GhidraLaunchable {
*/
public void run(String[] params, TaskMonitor monitor) throws Exception, CancelledException {
clearParams();
checkRequiredParam(params, 0, "command");
String command = params[0];
if (!COMMAND_SET.contains(command)) {
@ -420,7 +393,6 @@ public class BSimLaunchable implements GhidraLaunchable {
monitor.setCancelEnabled(true);
clearParams();
List<String> subParams = readOptions(command, params, 2);
initializeApplication(command);
@ -458,8 +430,10 @@ public class BSimLaunchable implements GhidraLaunchable {
doGenerateSigs(subParams, monitor);
}
else if (COMMAND_COMMIT_SIGS.equals(command)) {
if (overrideOption) {
setupURLs(ghidraURLOption, urlstring);
// --override option specified ghidra URL
String ghidraURLOverride = optionValueMap.get(OVERRIDE_OPTION);
if (ghidraURLOverride != null) {
setupURLs(ghidraURLOverride, urlstring);
}
else {
bsimURL = BSimClientFactory.deriveBSimURL(urlstring);
@ -500,10 +474,12 @@ public class BSimLaunchable implements GhidraLaunchable {
}
private void processSigAndUpdateOptions(String urlstring) throws MalformedURLException {
String bsimURLOption = optionValueMap.get(BSIM_URL_OPTION);
String configOption = optionValueMap.get(CONFIG_OPTION);
if (configOption != null) {
if (bsimURLOption != null) {
throw new IllegalArgumentException(
"bsim= and config= parameters may not both be present");
BSIM_URL_OPTION + " and " + CONFIG_OPTION + " options may not both be present");
}
setupGhidraURL(urlstring);
}
@ -512,7 +488,7 @@ public class BSimLaunchable implements GhidraLaunchable {
}
else {
throw new IllegalArgumentException(
"Must specify either \"bsim=\" or \"config=\" option is required");
"Must specify either " + BSIM_URL_OPTION + " or " + CONFIG_OPTION + " option");
}
}
@ -543,6 +519,10 @@ public class BSimLaunchable implements GhidraLaunchable {
String configTemplate = params.get(0);
boolean noTrackCallGraph = booleanOptions.contains(NO_CALLGRAPH_OPTION);
String nameOption = optionValueMap.get(NAME_OPTION);
String ownerOption = optionValueMap.get(OWNER_OPTION);
String descOption = optionValueMap.get(DESCRIPTION_OPTION);
try (BulkSignatures bsim = getBulkSignatures()) {
bsim.createDatabase(configTemplate, nameOption, ownerOption, descOption,
!noTrackCallGraph);
@ -551,19 +531,20 @@ public class BSimLaunchable implements GhidraLaunchable {
private void doGenerateSigs(List<String> params, TaskMonitor monitor)
throws Exception, CancelledException {
// concurrent bsim= and config= option use already checked
// concurrent --bsim and --config option use already checked
if (params.size() > 1) {
throw new IllegalArgumentException("Invalid generatesigs parameter use!");
}
boolean commitOption = booleanOptions.contains(COMMIT_OPTION);
boolean overwriteOption = booleanOptions.contains(OVERWRITE_OPTION);
String configOption = optionValueMap.get(CONFIG_OPTION);
String xmlDirectory = null;
if (params.size() == 1) {
xmlDirectory = params.get(0);
if (configOption != null && commitOption) {
throw new IllegalArgumentException(
"Invalid option use with config= option: " + COMMIT_OPTION);
"Invalid option use with " + CONFIG_OPTION + " option: " + COMMIT_OPTION);
}
}
else {
@ -588,19 +569,20 @@ public class BSimLaunchable implements GhidraLaunchable {
private void doGenerateUpdates(List<String> params, TaskMonitor monitor)
throws Exception, CancelledException {
// concurrent bsim= and config= option use already checked
// concurrent --bsim and --config option use already checked
if (params.size() > 1) {
throw new IllegalArgumentException("Invalid generateupdates parameter use!");
}
boolean commitOption = booleanOptions.contains(COMMIT_OPTION);
boolean overwriteOption = booleanOptions.contains(OVERWRITE_OPTION);
String configOption = optionValueMap.get(CONFIG_OPTION);
String xmlDirectory = null;
if (params.size() == 1) {
xmlDirectory = params.get(0);
if (configOption != null && commitOption) {
throw new IllegalArgumentException(
"Invalid option use with config= option: " + COMMIT_OPTION);
"Invalid option use with " + CONFIG_OPTION + " option: " + COMMIT_OPTION);
}
}
@ -640,17 +622,16 @@ public class BSimLaunchable implements GhidraLaunchable {
if (params.size() < 1) {
throw new IllegalArgumentException("Missing directory containing signature files");
}
if (!overrideOption && ghidraURLOption != null) {
throw new IllegalArgumentException(
"The \"ghidra=\" option use requires \"override\" option");
}
String xmlDirectory = params.get(0);
File dir = checkDirectory(xmlDirectory);
boolean hasOverride = optionValueMap.containsKey(OVERRIDE_OPTION);
String md5Filter = optionValueMap.get(MD5_OPTION);
try (BulkSignatures bsim = getBulkSignatures()) {
bsim.sendXmlToQueryServer(dir, overrideOption ? ghidraURL : null, filterOption,
monitor);
bsim.sendXmlToQueryServer(dir, hasOverride ? ghidraURL : null, md5Filter, monitor);
}
}
@ -678,10 +659,17 @@ public class BSimLaunchable implements GhidraLaunchable {
}
private void fillinSingleExeSpecifier(ExeSpecifier spec) throws IllegalArgumentException {
String md5Option = optionValueMap.get(MD5_OPTION);
String nameOption = optionValueMap.get(NAME_OPTION);
String archOption = optionValueMap.get(ARCH_OPTION);
String compOption = optionValueMap.get(COMPILER_OPTION);
if (md5Option != null) {
if (!isAllNull(nameOption, archOption, compOption)) {
throw new IllegalArgumentException(
"The name=, arch= and compiler= options are not valid when md5= option is specified.");
"The " + NAME_OPTION + ", " + ARCH_OPTION + ", " + COMPILER_OPTION +
" options are not valid when " + MD5_OPTION + " option is specified.");
}
spec.exemd5 = md5Option;
}
@ -691,14 +679,18 @@ public class BSimLaunchable implements GhidraLaunchable {
spec.execompname = compOption;
}
else {
throw new IllegalArgumentException("Must specify either \"md5=\" or \"name=\" option");
throw new IllegalArgumentException(
"Must specify either " + MD5_OPTION + " or " + NAME_OPTION + " option");
}
}
private void doListFunctions(List<String> params) throws IOException, LSHException {
Integer maxFunc = parsePositiveIntegerOption(MAX_FUNC_OPTION);
QueryName query = new QueryName();
fillinSingleExeSpecifier(query.spec);
if (maxFunc != null) {
query.maxfunc = maxFunc;
}
@ -792,17 +784,28 @@ public class BSimLaunchable implements GhidraLaunchable {
private void doListExes(List<String> params) throws IOException, LSHException {
int limit = DEFAULT_LIST_EXE_LIMIT;
Integer limitOption = parsePositiveIntegerOption(LIMIT_OPTION);
if (limitOption != null) {
limit = limitOption;
}
boolean includeLibs = booleanOptions.contains(INCLUDE_LIBS_OPTION);
String md5Option = optionValueMap.get(MD5_OPTION);
String nameOption = optionValueMap.get(NAME_OPTION);
String archOption = optionValueMap.get(ARCH_OPTION);
String compOption = optionValueMap.get(COMPILER_OPTION);
String sortColumnOption = optionValueMap.get(SORT_COL_OPTION);
try (BulkSignatures bsim = getBulkSignatures()) {
List<ExecutableRecord> exeList = bsim.getExes(limit, md5Option, nameOption, archOption,
compOption, sortColumn, includeLibs);
compOption, sortColumnOption, includeLibs);
for (ExecutableRecord exeRec : exeList) {
Msg.info(this, exeRec.printRaw());
}
String summary = exeList.size() + " executables found";
if (limit > 0 && limit == exeList.size()) {
summary += " (results limit reached)";
}
Msg.info(this, summary);
}
}
@ -814,7 +817,13 @@ public class BSimLaunchable implements GhidraLaunchable {
* @throws LSHException if there's an error issuing the query
*/
private void doGetCount(List<String> params) throws IOException, LSHException {
boolean includeFakes = booleanOptions.contains(INCLUDE_LIBS_OPTION);
String md5Option = optionValueMap.get(MD5_OPTION);
String nameOption = optionValueMap.get(NAME_OPTION);
String archOption = optionValueMap.get(ARCH_OPTION);
String compOption = optionValueMap.get(COMPILER_OPTION);
try (BulkSignatures bsim = getBulkSignatures()) {
int count = bsim.getCount(md5Option, nameOption, archOption, compOption, includeFakes);
System.out.println("Matching executable count: " + count);
@ -832,9 +841,14 @@ public class BSimLaunchable implements GhidraLaunchable {
* @throws LSHException if there's an error issuing the query
*/
private void doInstallMetadata(List<String> params) throws IOException, LSHException {
String nameOption = optionValueMap.get(NAME_OPTION);
String ownerOption = optionValueMap.get(OWNER_OPTION);
String descOption = optionValueMap.get(DESCRIPTION_OPTION);
if (isAllNull(nameOption, ownerOption, descOption)) {
throw new IllegalArgumentException(
"Missing one or more metadata options: [name=..] [owner=..] [description=..]");
throw new IllegalArgumentException("Missing one or more metadata options: " +
NAME_OPTION + ", " + OWNER_OPTION + ", " + DESCRIPTION_OPTION);
}
try (BulkSignatures bsim = getBulkSignatures()) {
@ -920,30 +934,30 @@ public class BSimLaunchable implements GhidraLaunchable {
//@formatter:off
System.err.println(
"USAGE: bsim [command] required-args... [OPTIONS...]\n" +
" createdatabase <bsimURL> <config_template> [name=\"<name>\"] [owner=\"<owner>\"] [description=\"<text>\"] [--nocallgraph]\n" +
" setmetadata <bsimURL> [name=\"<name>\"] [owner=\"<owner>\"] [description=\"<text>\"]\n" +
" createdatabase <bsimURL> <config_template> [--name|-n \"<name>\"] [--owner|-o \"<owner>\"] [--description|-d \"<text>\"] [--nocallgraph]\n" +
" setmetadata <bsimURL> [--name|-n \"<name>\"] [--owner|-o \"<owner>\"] [--description|-d \"<text>\"]\n" +
" addexecategory <bsimURL> <category_name> [--date]\n" +
" addfunctiontag <bsimURL> <tag_name>\n" +
" dropindex <bsimURL>\n" +
" rebuildindex <bsimURL>\n" +
" prewarm <bsimURL>\n" +
" generatesigs <ghidraURL> </xmldirectory> config=<config_template> [--overwrite]\n" +
" generatesigs <ghidraURL> </xmldirectory> bsim=<bsimURL> [--commit] [--overwrite]\n" +
" generatesigs <ghidraURL> bsim=<bsimURL>\n" +
" commitsigs <bsimURL> </xmldirectory> [md5=<hash>] [override=<ghidraURL>]\n" +
" generateupdates <ghidraURL> </xmldirectory> config=<config_template> [--overwrite]\n" +
" generateupdates <ghidraURL> </xmldirectory> bsim=<bsimURL> [--commit] [--overwrite]\n" +
" generateupdates <ghidraURL> bsim=<bsimURL>\n" +
" generatesigs <ghidraURL> </xmldirectory> --config|-c <config_template> [--overwrite]\n" +
" generatesigs <ghidraURL> </xmldirectory> --bsim|-b <bsimURL> [--commit] [--overwrite]\n" +
" generatesigs <ghidraURL> --bsim|-b <bsimURL>\n" +
" commitsigs <bsimURL> </xmldirectory> [--md5|-m <hash>] [--override <ghidraURL>]\n" +
" generateupdates <ghidraURL> </xmldirectory> --config|-c <config_template> [--overwrite]\n" +
" generateupdates <ghidraURL> </xmldirectory> --bsim|-b <bsimURL> [--commit] [--overwrite]\n" +
" generateupdates <ghidraURL> --bsim|-b <bsimURL>\n" +
" commitupdates <bsimURL> </xmldirectory>\n" +
" listexes <bsimURL> [md5=<hash>] [name=<exe_name>] [arch=<languageID>] [compiler=<cspecID>] [sortcol=<column_name>] [limit=<exe_count>] [--includelibs]\n" +
" getexecount <bsimURL> [md5=<hash>] [name=<exe_name>] [arch=<languageID>] [compiler=<cspecID>] [--includelibs]\n" +
" delete <bsimURL> [md5=<hash>] [name=<exe_name> [arch=<languageID>] [compiler=<cspecID>]]\n" +
" listfuncs <bsimURL> [md5=<hash>] [name=<exe_name> [arch=<languageID>] [compiler=<cspecID>]] [--printselfsig] [--callgraph] [--printjustexe] [maxfunc=<max_count>]\n" +
" dumpsigs <bsimURL> </xmldirectory> [md5=<hash>] [name=<exe_name> [arch=<languageID>] [compiler=<cspecID>]]\n" +
" listexes <bsimURL> [--md5|-m <hash>] [--name|-n <exe_name>] [--arch|-a <languageID>] [--compiler <cspecID>] [--sortcol|-s md5|name] [--limit|-l <exe_count>] [--includelibs]\n" +
" getexecount <bsimURL> [--md5|-m <hash>] [--name|-n <exe_name>] [--arch|-a <languageID>] [--compiler <cspecID>] [--includelibs]\n" +
" delete <bsimURL> [--md5|-m <hash>] [--name|-n <exe_name> [--arch|-a <languageID>] [--compiler <cspecID>]]\n" +
" listfuncs <bsimURL> [--md5|-m <hash>] [--name|-n <exe_name> [--arch|-a <languageID>] [--compiler <cspecID>]] [--printselfsig] [--callgraph] [--printjustexe] [--maxfunc <max_count>]\n" +
" dumpsigs <bsimURL> </xmldirectory> [--md5|-m <hash>] [--name|-n <exe_name> [--arch|-a <languageID>] [--compiler <cspecID>]]\n" +
"\n" +
"Global options:\n" +
" user=<username>\n" +
" cert=</certfile-path>\n" +
" --user|-u <username>\n" +
" --cert </certfile-path>\n" +
"\n" +
"Enumerated Options:\n" +
" <config_template> - large_32 | medium_32 | medium_64 | medium_cpool | medium_nosize \n" +
@ -957,7 +971,8 @@ public class BSimLaunchable implements GhidraLaunchable {
"Ghidra URL Forms (ghidraURL):\n" +
" ghidra://<hostname>[:<port>]/<repo-name>[/<folder-path>]\n" +
" ghidra:/[<local-dirpath>/]<project-name>[?/<folder-path>]\n" +
"\n");
"\n" +
"NOTE: Options with values may also be specified using the form: --option=value\n");
//@formatter:on
}
@ -991,6 +1006,10 @@ public class BSimLaunchable implements GhidraLaunchable {
private void initializeApplication(String command) throws IOException {
int initType = COMMANDS_WITH_REPO_ACCESS.contains(command) ? 2 : 1;
if (layout != null) {
String connectingUserName = optionValueMap.get(USER_OPTION);
String certOption = optionValueMap.get(CERT_OPTION);
initializeApplication(layout, initType, connectingUserName, certOption);
}
}

View File

@ -37,6 +37,7 @@ import ghidra.features.bsim.query.client.tables.ExeTable.ExeTableOrderColumn;
import ghidra.features.bsim.query.description.*;
import ghidra.features.bsim.query.protocol.*;
import ghidra.features.bsim.query.protocol.ResponseDelete.DeleteResult;
import ghidra.framework.Application;
import ghidra.framework.client.ClientUtil;
import ghidra.framework.protocol.ghidra.GhidraURL;
import ghidra.program.model.listing.*;
@ -184,6 +185,10 @@ public class BulkSignatures implements AutoCloseable {
insertreq.path_override = GhidraURL.getProjectPathname(ghidraOverrideURL);
}
loadSignatureXml(file, insertreq.manage);
if (insertreq.manage.numFunctions() == 0) {
Msg.warn(this, file.getName() + ": does not define any functions");
continue;
}
if (insertreq.execute(querydb) == null) {
Error lastError = querydb.getLastError();
if ((lastError.category == ErrorCategory.Format) ||
@ -646,7 +651,7 @@ public class BulkSignatures implements AutoCloseable {
establishQueryServerConnection(false);
ExeTableOrderColumn sortEnum;
if (sortCol != null) {
sortEnum = ExeTableOrderColumn.valueOf(sortCol);
sortEnum = ExeTableOrderColumn.valueOf(sortCol.toUpperCase());
}
else {
sortEnum = ExeTableOrderColumn.MD5;
@ -961,11 +966,12 @@ public class BulkSignatures implements AutoCloseable {
protected File establishTemporaryDirectory(String xmldir) throws IOException {
File dir;
if (xmldir == null) {
String tempDirString = System.getProperty("java.io.tmpdir");
if (tempDirString == null) {
File tmpDir = Application.getUserTempDirectory();
if (tmpDir == null) {
throw new IOException("Could not find temporary directory");
}
dir = new File(tempDirString, "bulkinsert_xml");
dir = new File(tmpDir, "bulkinsert_xml");
deleteTemporaryDirectory(dir);
}
else {
dir = new File(xmldir);
@ -983,6 +989,9 @@ public class BulkSignatures implements AutoCloseable {
}
private void deleteTemporaryDirectory(File tempDir) throws IOException {
if (!tempDir.exists()) {
return;
}
File[] listFiles = tempDir.listFiles();
if (listFiles == null) {
throw new IOException(
@ -1106,6 +1115,7 @@ public class BulkSignatures implements AutoCloseable {
if (manager.numFunctions() == 0) {
Msg.warn(this, program.getDomainFile().getName() +
" contains no functions with signatures");
return;
}
FileWriter fwrite = new FileWriter(file);
manager.saveXml(fwrite);

View File

@ -3,7 +3,7 @@
# Command-line script for interacting with a BSim database
# maximum heap memory (may be increased)
MAXMEM=1G
MAXMEM=2G
# launch mode (fg, bg, debug, debug-suspend)
LAUNCH_MODE=fg

View File

@ -3,9 +3,8 @@
@echo off
setlocal
:: Maximum heap memory may be changed if default is inadequate. This will generally be up to 1/4 of
:: the physical memory available to the OS. Uncomment MAXMEM setting if non-default value is needed.
::set MAXMEM=2G
:: maximum heap memory (may be increased)
set MAXMEM=2G
:: launch mode (fg, bg, debug, debug-suspend)
set LAUNCH_MODE=fg

View File

@ -23,13 +23,13 @@ Non-shared projects are locked when open, and the lock will prevent the signatur
<pre><code class="language-bash">cd &lt;ghidra_install_dir&gt;/support
mkdir ~/bsim_sigs
./bsim generatesigs ghidra:/&lt;ghidra_project_dir&gt;/postgres_object_files bsim=file:/&lt;database_dir&gt;/example ~/bsim_sigs
./bsim generatesigs ghidra:/&lt;ghidra_project_dir&gt;/postgres_object_files --bsim file:/&lt;database_dir&gt;/example ~/bsim_sigs
</code></pre>
<ul>
<li>The <code>ghidra:/</code> argument is the local project which holds the analyzed binaries.
Note that there is only one forward slash in the URL for a local project.</li>
<li>The <code>bsim=</code> argument is the URL of the BSim database.
<li>The <code>--bsim</code> argument is the URL of the BSim database.
This command does not add any signatures to the database, but it does query the database for its settings.</li>
</ul>

View File

@ -22,12 +22,12 @@ To generate the signature files, execute the following commands in a shell (adju
```bash
cd <ghidra_install_dir>/support
mkdir ~/bsim_sigs
./bsim generatesigs ghidra:/<ghidra_project_dir>/postgres_object_files bsim=file:/<database_dir>/example ~/bsim_sigs
./bsim generatesigs ghidra:/<ghidra_project_dir>/postgres_object_files --bsim file:/<database_dir>/example ~/bsim_sigs
```
- The ``ghidra:/`` argument is the local project which holds the analyzed binaries.
Note that there is only one forward slash in the URL for a local project.
- The ``bsim=`` argument is the URL of the BSim database.
- The ``--bsim`` argument is the URL of the BSim database.
This command does not add any signatures to the database, but it does query the database for its settings.
## Committing Signature Files