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 Use a command-line like this to generate and commit signatures from a Ghidra Server
repository to the Elasticsearch database created above: 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 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 panel in order to place queries to your Elasticsearch deployment. See the BSim

View file

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

View file

@ -214,7 +214,7 @@
<TR> <TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim_ctl start /path/to/datadir <TD><CODE class="computeroutput">$(ROOT)/support/bsim_ctl start /path/to/datadir
port=8000</CODE></TD> --port&nbsp;8000</CODE></TD>
</TR> </TR>
<TR> <TR>
@ -236,7 +236,7 @@
be reused.</P> be reused.</P>
<P>The <SPAN class="bold"><STRONG>start</STRONG></SPAN> command can take an optional <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 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= 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. "command"><STRONG>bsim</STRONG></SPAN> command described below, must specify the port.
@ -293,7 +293,7 @@
<DD> <DD>
<P><CODE class="computeroutput">bsim_ctl start /path/to/datadir <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 <P>This is currently the default. No authentication is performed and privilege
is granted based on the user name presented. Masquerading is possible.</P> is granted based on the user name presented. Masquerading is possible.</P>
@ -304,7 +304,7 @@
<DD> <DD>
<P><CODE class="computeroutput">bsim_ctl start /path/to/datadir <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 <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 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> <DT><SPAN class="term"><SPAN class="bold"><STRONG>pki</STRONG></SPAN></SPAN></DT>
<DD> <DD>
<P><CODE class="computeroutput">bsim_ctl start /path/to/datadir auth=pki <P><CODE class="computeroutput">bsim_ctl start /path/to/datadir --auth&nbsp;pki
ca=/path/to/rootcert</CODE></P> --cafile&nbsp;"/path/to/rootcert"</CODE></P>
<P>Users are authenticated by PKI certificates. Upon initialization, the BSim <P>Users are authenticated by PKI certificates. Upon initialization, the BSim
server must be provided (via the <SPAN class= 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 for the certificate authorities used to issue user's certificates. The file
consists of the authoritative certificates in PEM format concatenated consists of the authoritative certificates in PEM format concatenated
together.</P> together.</P>
@ -338,7 +338,7 @@
<P>With PKI authentication enabled, at the time a new user role is established <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 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= 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 "#PostAddUser" title="Adding Users to the Database">&ldquo;Adding Users to the
Database&rdquo;</A>.</P> Database&rdquo;</A>.</P>
</DD> </DD>
@ -358,7 +358,7 @@
<TABLE border="0" summary="Simple list" class="simplelist"> <TABLE border="0" summary="Simple list" class="simplelist">
<TR> <TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim_ctl changeauth <TD><CODE class="computeroutput">$(ROOT)/support/bsim_ctl changeauth
/datadir/path auth=password</CODE></TD> /datadir/path --auth&nbsp;password</CODE></TD>
</TR> </TR>
</TABLE> </TABLE>
</DIV> </DIV>
@ -401,7 +401,7 @@
<TR> <TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim_ctl adduser <SPAN class= <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> </TR>
</TABLE> </TABLE>
</DIV> </DIV>
@ -410,7 +410,7 @@
initially be set to 'changeme'. If PKI authentication has been set for the server, The 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 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 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 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 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> 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"> <TABLE border="0" summary="Simple list" class="simplelist">
<TR> <TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim setmetadata <SPAN class= <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>
<TR> <TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim setmetadata <SPAN class= <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>
<TR> <TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim setmetadata <SPAN class= <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> </TR>
</TABLE> </TABLE>
</DIV> </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. 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 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= 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 "bold"><STRONG>--name</STRONG></SPAN>, <SPAN class="bold"><STRONG>--owner</STRONG></SPAN>, or
<SPAN class="bold"><STRONG>description=</STRONG></SPAN> respectively. Quoting may be <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> necessary to get some strings to be interpreted as a single command-line parameter.</P>
<DIV class="sect2"> <DIV class="sect2">

View file

@ -112,20 +112,20 @@
"command"><STRONG>bsim generatesigs</STRONG></SPAN> command. Signatures may be written as "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 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 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 database configuration may be specified using the <EM>--config</EM> option in lieu of a BSim database URL
(<EM>bsimURL</EM>) if database specific executable categories and function tags are not (--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> utilized. Use of the <EM>--config</EM> option does not require a running BSim server.</P>
<DIV class="informalexample"> <DIV class="informalexample">
<TABLE border="0" summary="Simple list" class="simplelist"> <TABLE border="0" summary="Simple list" class="simplelist">
<TR> <TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim generatesigs <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> [--overwrite]<BR>
$(ROOT)/support/bsim generatesigs &lt;ghidraURL&gt; &lt;/xmldirectory&gt; $(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; $(ROOT)/support/bsim generatesigs &lt;ghidraURL&gt;
bsim=&lt;bsimURL&gt;</CODE></TD> --bsim&nbsp;&lt;bsimURL&gt;</CODE></TD>
</TR> </TR>
</TABLE> </TABLE>
</DIV> </DIV>
@ -137,7 +137,7 @@
<TR> <TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim generatesigs <TD><CODE class="computeroutput">$(ROOT)/support/bsim generatesigs
ghidra://localhost/repo/folder /xmldirectory ghidra://localhost/repo/folder /xmldirectory
bsim=postgresql://localhost/repo</CODE></TD> --bsim&nbsp;postgresql://localhost/repo</CODE></TD>
</TR> </TR>
</TABLE> </TABLE>
</DIV> </DIV>
@ -148,7 +148,7 @@
<TABLE border="0" summary="Simple list" class="simplelist"> <TABLE border="0" summary="Simple list" class="simplelist">
<TR> <TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim generatesigs <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> --commit</CODE></TD>
</TR> </TR>
</TABLE> </TABLE>
@ -176,7 +176,7 @@
the signature generation process, such as database specific executable categories or the signature generation process, such as database specific executable categories or
function tags. As in the example above, configuration information function tags. As in the example above, configuration information
is pulled from the BSim server and signatures are generated from the Ghidra Server 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 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 database and there are no executable categories or function tags, the BSim server
does not need to be running.</P> does not need to be running.</P>
@ -199,7 +199,7 @@
<TABLE border="0" summary="Simple list" class="simplelist"> <TABLE border="0" summary="Simple list" class="simplelist">
<TR> <TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim commitsigs <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> </TR>
</TABLE> </TABLE>
</DIV> </DIV>
@ -215,7 +215,7 @@
"emphasis"><EM>repository</EM></SPAN> and <SPAN class="emphasis"><EM>path</EM></SPAN> "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 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 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> Ghidra URL may be specified.</P>
<P>The <SPAN class="command"><STRONG>bsim commitsigs</STRONG></SPAN> command can be <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"> <TABLE border="0" summary="Simple list" class="simplelist">
<TR> <TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim delete <SPAN class= <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> "emphasis"><EM>7abf...</EM></SPAN></CODE></TD>
</TR> </TR>
<TR> <TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim delete <SPAN class= <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> "emphasis"><EM>...</EM></SPAN></CODE></TD>
</TR> </TR>
</TABLE> </TABLE>
</DIV> </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 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> 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 <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"> <TABLE border="0" summary="Simple list" class="simplelist">
<TR> <TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim generateupdates <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> [--overwrite]<BR>
$(ROOT)/support/bsim generateupdates &lt;ghidraURL&gt; &lt;/xmldirectory&gt; $(ROOT)/support/bsim generateupdates &lt;ghidraURL&gt; &lt;/xmldirectory&gt;
bsim=&lt;bsimURL&gt; [--commit] [--overwrite]<BR> --bsim&nbsp;&lt;bsimURL&gt; [--commit] [--overwrite]<BR>
$(ROOT)/support/bsim generateupdates &lt;ghidraURL&gt; bsim=&lt;bsimURL&gt;<BR> $(ROOT)/support/bsim generateupdates &lt;ghidraURL&gt; --bsim&nbsp;&lt;bsimURL&gt;<BR>
<BR> <BR>
$(ROOT)/support/bsim commitupdates &lt;bsimURL&gt; $(ROOT)/support/bsim commitupdates &lt;bsimURL&gt;
&lt;/xmldirectory&gt;</CODE></TD> &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 stripped down metadata XML files for every executable contained within the repository
folder specified by the <EM>ghidraURL</EM>. Just like the <SPAN class= folder specified by the <EM>ghidraURL</EM>. Just like the <SPAN class=
"bold"><STRONG>generatesigs</STRONG></SPAN> command, it can take an optional <SPAN "bold"><STRONG>generatesigs</STRONG></SPAN> command, it can take an optional <SPAN
class="bold"><STRONG>config=<EM>config_template</EM></STRONG></SPAN> parameter, which 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. It can also take an 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 optional <SPAN class="bold"><STRONG>--overwrite</STRONG></SPAN> parameter, causing it
to overwrite any previously generated XML files. If a to overwrite any previously generated XML files. If the
<STRONG>bsim=<EM>bsimURL</EM></STRONG> is specified with the <STRONG>--commit</STRONG> <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 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 always performed using the specified <EM>bsimURL</EM> if an <EM>xmldirectory</EM> is
not specified.</P> not specified.</P>
@ -635,7 +637,7 @@ public void adjustTags(Address myaddress) throws Exception {
<TABLE border="0" summary="Simple list" class="simplelist"> <TABLE border="0" summary="Simple list" class="simplelist">
<TR> <TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim dropindex <SPAN class= <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> </TR>
</TABLE> </TABLE>
</DIV> </DIV>
@ -646,7 +648,7 @@ public void adjustTags(Address myaddress) throws Exception {
<TABLE border="0" summary="Simple list" class="simplelist"> <TABLE border="0" summary="Simple list" class="simplelist">
<TR> <TR>
<TD><CODE class="computeroutput">$(ROOT)/support/bsim rebuildindex <SPAN class= <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> </TR>
</TABLE> </TABLE>
</DIV> </DIV>

View file

@ -29,6 +29,7 @@ import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn; import javax.naming.ldap.Rdn;
import javax.security.auth.DestroyFailedException; import javax.security.auth.DestroyFailedException;
import org.apache.commons.lang3.StringUtils;
import org.xml.sax.ErrorHandler; import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@ -40,7 +41,7 @@ import ghidra.framework.client.ClientUtil;
import ghidra.net.ApplicationKeyManagerUtils; import ghidra.net.ApplicationKeyManagerUtils;
import ghidra.util.Msg; import ghidra.util.Msg;
import ghidra.util.exception.AssertException; import ghidra.util.exception.AssertException;
import ghidra.util.task.TaskMonitor; import ghidra.util.exception.CancelledException;
import ghidra.util.xml.SpecXmlUtils; import ghidra.util.xml.SpecXmlUtils;
import ghidra.xml.NonThreadedXmlPullParserImpl; import ghidra.xml.NonThreadedXmlPullParserImpl;
import ghidra.xml.XmlPullParser; import ghidra.xml.XmlPullParser;
@ -48,22 +49,68 @@ import utilities.util.FileUtilities;
public class BSimControlLaunchable implements GhidraLaunchable { public class BSimControlLaunchable implements GhidraLaunchable {
public static final String PORT_OPTION = "port="; // bsim_ctl commands
public static final String CAFILE_OPTION = "cafile="; public final static String COMMAND_START = "start";
public static final String AUTH_OPTION = "auth="; public final static String COMMAND_STOP = "stop";
public static final String DN_OPTION = "dn="; public final static String COMMAND_RESET_PASSWORD = "resetpassword";
public static final String CERT_OPTION = "cert="; 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 NO_LOCAL_AUTH_OPTION = "--noLocalAuth";
public static final String USER_OPTION = "user=";
public static final String FORCE_OPTION = "--force"; public static final String FORCE_OPTION = "--force";
private final static String START_COMMAND = "start"; private static final Map<String, String> SHORTCUT_OPTION_MAP = new HashMap<>();
private final static String STOP_COMMAND = "stop"; static {
private final static String PASSWORD_COMMAND = "resetpassword"; SHORTCUT_OPTION_MAP.put("-a", AUTH_OPTION);
private final static String PRIVILEGE_COMMAND = "changeprivilege"; SHORTCUT_OPTION_MAP.put("-p", PORT_OPTION);
private final static String ADDUSER_COMMAND = "adduser"; SHORTCUT_OPTION_MAP.put("-u", USER_OPTION);
private final static String DROPUSER_COMMAND = "dropuser"; }
private final static String RESET_COMMAND = "changeauth";
//@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 = "postgresql";
private final static String POSTGRES_BUILD_SCRIPT = "Ghidra/Features/BSim/make-postgres.sh"; private final static String POSTGRES_BUILD_SCRIPT = "Ghidra/Features/BSim/make-postgres.sh";
private final static String POSTGRES_CONFIGFILE = "postgresql.conf"; 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_NONE = 0;
private final static int AUTHENTICATION_PASSWORD = 1; private final static int AUTHENTICATION_PASSWORD = 1;
private final static int AUTHENTICATION_PKI = 2; 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 GhidraApplicationLayout layout;
private File postgresRoot; // Directory containing postgres software
private File postgresControl; // "pg_ctl" utility within postgres software private File dataDirectory; // Directory containing postgres datafiles
private File certAuthorityFile = null; // Certificate authority file provided by the user private File postgresRoot; // Directory containing postgres software
private String certParameter = null; // Path to certificate provided by user private File postgresControl; // "pg_ctl" utility within postgres software
private String distinguishedName = null; // Certificate distinguished name provided by the user private File certAuthorityFile; // Certificate authority file provided by the user
private String commonName = null; // Common name extracted from distinguishedName private String certParameter; // Path to certificate provided by user
private String connectingUserName = null; // User-name used to establish connection private String distinguishedName; // Certificate distinguished name provided by the user
private String specifiedUserName = null; // -username- (add/drop) operation is being performed on private String commonName; // Common name extracted from distinguishedName
private boolean adminPrivilegeRequested = false; // true is attempting to give user admin privileges private String connectingUserName; // User-name used to establish connection
private boolean forceShutdown = false; // Whether or not to force a shutdown (--force) private String specifiedUserName; // -username- (add/drop) operation is being performed on
private String loadLibraryVar = null; // Environment variable pointing to postgres shared libraries private boolean adminPrivilegeRequested; // true is attempting to give user admin privileges
private String loadLibraryValue = null; // Directory containing shared libraries within postgres software private boolean forceShutdown; // Whether or not to force a shutdown (--force)
private int port = -1; // Port over which to connect to postgres server, (-1 indicates default port is used) private String loadLibraryVar; // Environment variable pointing to postgres shared libraries
private int localAuthentication = AUTHENTICATION_NONE; // Type of authentication required for local connections private String loadLibraryValue; // Directory containing shared libraries within postgres software
private int hostAuthentication = AUTHENTICATION_NONE; // Type of authentication for remote connections private int port; // Port over which to connect to postgres server, (-1 indicates default port is used)
private boolean authConfigPresent = false; // True if the [auth=..] option or the [--noLocalAuth] is present private int localAuthentication; // Type of authentication required for local connections
private File passwordFile = null; // File containing newly established password private int hostAuthentication; // Type of authentication for remote connections
private char[] adminPasswordData = null; // Password data being sent to postgres server for authentication 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 // Database connection that can be persisted so we don't need to recreate one
// for every call. // for every call.
private Connection localConnection; 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 BSimControlLaunchable() {
public ArgumentException(String message) { }
super(message);
} 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 * Read required parameters followed by optional parameters
* The streams can be optionally suppressed or dumped to System.out * @param params is the original array of command line parameters
*/ */
private class IOThread extends Thread { private String readCommandLine(String[] params) throws IllegalArgumentException, IOException {
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) { int slot = 0;
shellOutput = new BufferedReader(new InputStreamReader(input));
suppressOutput = suppressOut; 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 readOptions(command, params, slot);
public void run() {
String line = null; return command;
try { }
while ((line = shellOutput.readLine()) != null) {
if (!suppressOutput) { /**
System.out.println(line); * 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) String option = optionName;
System.err.println("Unexpected Exception: " + e.getMessage());
e.printStackTrace(System.err); 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() { private void checkRequiredParam(String[] params, int index, String name) {
// Constructor for main launcher 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 * 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 * X509 certificate distinguished name. Try to extract the common name portion of the
* distinguished name and assign it to -commonName- * 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; commonName = null;
try { try {
LdapName ldapName = new LdapName(distinguishedName); LdapName ldapName = new LdapName(distinguishedName);
@ -192,11 +414,11 @@ public class BSimControlLaunchable implements GhidraLaunchable {
} }
} }
if (commonName == null) { if (commonName == null) {
throw new ArgumentException("Missing common name attribute"); throw new IllegalArgumentException("Missing common name attribute");
} }
} }
catch (Exception e) { 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 * @throws IOException if the password file cannot be deleted
*/ */
private void cleanupPasswordData() throws IOException { private void cleanupPasswordData() throws IOException {
clearPasswordData(adminPasswordData);
adminPasswordData = null;
if (passwordFile != null) { if (passwordFile != null) {
if (!passwordFile.delete()) { if (!passwordFile.delete()) {
throw new IOException( throw new IOException(
@ -304,8 +530,6 @@ public class BSimControlLaunchable implements GhidraLaunchable {
} }
passwordFile = null; 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 * 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 * 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) { else if (hostAuthentication == AUTHENTICATION_PKI) {
if (commonName == null) { if (commonName == null) {
throw new GeneralSecurityException( throw new GeneralSecurityException(
"Distinguished name required for " + connectingUserName + " (dn=\"..\")"); "Distinguished name option (--dn) required for " + connectingUserName);
} }
checkCertAuthorityFile(); checkCertAuthorityFile();
} }
@ -717,19 +929,19 @@ public class BSimControlLaunchable implements GhidraLaunchable {
/** /**
* Scan the PostgreSQL data directory from the command-line * Scan the PostgreSQL data directory from the command-line
* Make sure the directory exists and establish the File object -dataDirectory- * Make sure the directory exists and establish the File object -dataDirectory-
* @param params are the command-line options * @param params are the command-line arguments
* @param slot is the position to retrieve the data directory * @param slot is the position to retrieve the data directory argument
* @throws ArgumentException if the data directory is invalid * @throws IllegalArgumentException if the data directory is invalid
* @throws IOException if the canonical file cannot be retrieved * @throws IOException if the canonical file cannot be retrieved
*/ */
private void scanDataDirectory(String[] params, int slot) private void scanDataDirectory(String[] params, int slot)
throws ArgumentException, IOException { throws IllegalArgumentException, IOException {
if (params.length <= slot) { if (params.length <= slot) {
throw new ArgumentException("Missing data directory"); throw new IllegalArgumentException("Missing data directory");
} }
dataDirectory = new File(params[slot]); dataDirectory = new File(params[slot]);
if (!dataDirectory.isDirectory()) { if (!dataDirectory.isDirectory()) {
throw new ArgumentException( throw new IllegalArgumentException(
"Data directory " + dataDirectory.getAbsolutePath() + " does not exist"); "Data directory " + dataDirectory.getAbsolutePath() + " does not exist");
} }
dataDirectory = dataDirectory.getCanonicalFile(); dataDirectory = dataDirectory.getCanonicalFile();
@ -737,13 +949,13 @@ public class BSimControlLaunchable implements GhidraLaunchable {
/** /**
* Scan the username from the command-line * Scan the username from the command-line
* @param params are the command-line options * @param params are the command-line arguments
* @param slot is the position to retrieve the username * @param slot is the position to retrieve the username argument
* @throws ArgumentException if the user name is not in the given params * @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) { if (params.length <= slot) {
throw new ArgumentException("Missing username"); throw new IllegalArgumentException("Missing username");
} }
specifiedUserName = params[slot]; specifiedUserName = params[slot];
} }
@ -751,13 +963,13 @@ public class BSimControlLaunchable implements GhidraLaunchable {
/** /**
* Scan command-line for a particular privilege level. Administrator privileges are * 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 * requested with the exact String "admin", anything is a request for a read-only user
* @param params are the command-line options * @param params are the command-line arguments
* @param slot is the position to retrieve the user name * @param slot is the position to retrieve the user name argument
* @throws ArgumentException the privilege parameter is missing * @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) { 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")) { if (params[slot].equals("admin")) {
adminPrivilegeRequested = true; adminPrivilegeRequested = true;
@ -766,7 +978,7 @@ public class BSimControlLaunchable implements GhidraLaunchable {
adminPrivilegeRequested = false; adminPrivilegeRequested = false;
} }
else { 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) { if (localAuthentication == AUTHENTICATION_PKI && certParameter == null) {
throw new GeneralSecurityException( 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"); File logFile = new File(dataDirectory, "logfile");
List<String> command = new ArrayList<String>(); List<String> command = new ArrayList<String>();
@ -883,58 +1095,6 @@ public class BSimControlLaunchable implements GhidraLaunchable {
FileUtilities.copyFile(copyFile, identFile, false, null); 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. * 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 * 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 SAXException if the {@link #tuneConfig(File, File, File, File, File)} call fails
* @throws GeneralSecurityException if there is no Distinguished Name supplied * @throws GeneralSecurityException if there is no Distinguished Name supplied
*/ */
private void resetCommand() private void changeAuthCommand()
throws IOException, InterruptedException, SAXException, GeneralSecurityException { throws IOException, InterruptedException, SAXException, GeneralSecurityException {
discoverPostgresInstall(); discoverPostgresInstall();
File configFile = new File(dataDirectory, POSTGRES_CONFIGFILE); 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(); localConnection = getOrCreateLocalConnection();
try { try {
if (adminPrivilegeRequested) { 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. * Runs the command specified by the given set of params.
* *
* @param params the command parameters * @param params the parameters specifying the command
* @param monitor the task monitor * @throws IllegalArgumentException if invalid params have been specified
* @throws Exception if there is a problem executing the command * @throws Exception if there's an error during the operation
*/ * @throws CancelledException if processing is cancelled
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
*/ */
public void run(String[] params) throws Exception { 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 @Override
public void launch(GhidraApplicationLayout ghidraLayout, String[] params) { public void launch(GhidraApplicationLayout ghidraLayout, String[] params) {
if (params.length <= 1) { if (params.length <= 1) {
//@formatter:off //@formatter:off
System.err.println("USAGE:"); System.err.println("USAGE: bsim_ctl [command] required-args... [OPTIONS...}\n");
System.err.println(" bsim_ctl start </datadir-path> [auth=pki|password|trust] [--noLocalAuth] [cafile=</cacert-path>] [dn=\"..\"]"); 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(" stop </datadir-path> [--force]");
System.err.println(" adduser </datadir-path> <username> [dn=\"..\"]"); System.err.println(" adduser </datadir-path> <username> [--dn \"<distinguished-name>\"]");
System.err.println(" dropuser </datadir-path> <username>"); System.err.println(" dropuser </datadir-path> <username>");
System.err.println(" changeauth </datadir-path> [auth=pki|password|trust] [--noLocalAuth] [cafile=</cacert-path>]"); System.err.println(" changeauth </datadir-path> [--auth|-a pki|password|trust] [--noLocalAuth] [--cafile \"</cacert-path>\"]");
System.err.println(" resetpassword <username>"); System.err.println(" resetpassword <username>");
System.err.println(" changeprivilege <username> admin|user"); System.err.println(" changeprivilege <username> admin|user");
System.err.println(); System.err.println();
System.err.println("Global options:"); System.err.println("Global options:");
System.err.println(" port=<portnum>"); System.err.println(" --port|-p <portnum>");
System.err.println(" user=<username>"); System.err.println(" --user|-u <username>");
System.err.println(" cert=</certfile-path>"); 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(); System.err.println();
//@formatter:on //@formatter:on
return; return;
} }
layout = ghidraLayout; // Save layout for when we need to initialize application layout = ghidraLayout; // Save layout for when we need to initialize application
boolean success = false;
try { try {
run(params); run(params);
success = true;
} }
catch (RuntimeException e) { catch (SAXException e1) {
e.printStackTrace(); System.err.println("Error in server configuation data");
System.exit(1); 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) { catch (Exception e) {
System.err.println("Unexpected error");
e.printStackTrace();
}
if (!success) {
System.exit(1); 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, public static boolean checkSettingsForInsert(DescriptionManager manage,
DatabaseInformation info) throws LSHException, DatabaseNonFatalException { DatabaseInformation info) throws LSHException, DatabaseNonFatalException {
if (manage.numFunctions() == 0) { if (manage.numFunctions() == 0) {
throw new DatabaseNonFatalException("ls ~/junk" + ""); throw new DatabaseNonFatalException("Empty signature file");
} }
int res = info.checkSignatureSettings(manage.getMajorVersion(), manage.getMinorVersion(), int res = info.checkSignatureSettings(manage.getMajorVersion(), manage.getMinorVersion(),
manage.getSettings()); manage.getSettings());

View file

@ -20,6 +20,7 @@ import java.io.IOException;
import java.net.*; import java.net.*;
import java.util.*; import java.util.*;
import org.apache.commons.lang3.StringUtils;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import ghidra.GhidraApplicationLayout; import ghidra.GhidraApplicationLayout;
@ -77,27 +78,29 @@ public class BSimLaunchable implements GhidraLaunchable {
private static Set<String> COMMANDS_WITH_REPO_ACCESS = private static Set<String> COMMANDS_WITH_REPO_ACCESS =
Set.of(COMMAND_GENERATE_SIGS, COMMAND_GENERATE_UPDATES); Set.of(COMMAND_GENERATE_SIGS, COMMAND_GENERATE_UPDATES);
/** // Options that require a value argument
* 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 NAME_OPTION = "--name";
private static final String BSIM_URL_OPTION = "bsim="; private static final String OWNER_OPTION = "--owner";
private static final String GHIDRA_URL_OPTION = "ghidra="; private static final String DESCRIPTION_OPTION = "--description";
private static final String NAME_OPTION = "name="; private static final String OVERRIDE_OPTION = "--override";
private static final String OWNER_OPTION = "owner="; private static final String CONFIG_OPTION = "--config";
private static final String DESCRIPTION_OPTION = "description="; private static final String MD5_OPTION = "--md5";
private static final String OVERRIDE_OPTION = "override="; private static final String MAX_FUNC_OPTION = "--maxfunc";
private static final String CONFIG_OPTION = "config="; private static final String ARCH_OPTION = "--arch";
private static final String MD5_OPTION = "md5="; private static final String COMPILER_OPTION = "--compiler";
private static final String MAX_FUNC_OPTION = "maxfunc="; private static final String LIMIT_OPTION = "--limit";
private static final String FILTER_OPTION = "filter="; private static final String SORT_COL_OPTION = "--sortcol";
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 // Global options that require a value argument
private static final String USER_OPTION = "user="; private static final String USER_OPTION = "--user";
private static final String CERT_OPTION = "cert="; 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); 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 CALL_GRAPH_OPTION = "--callgraph";
private static final String PRINT_JUST_EXE_OPTION = "--printjustexe"; 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 //@formatter:off
// Populate ALLOWED_OPTION_MAP for each command // Populate ALLOWED_OPTION_MAP for each command
private static final Set<String> CREATE_DATABASE_OPTIONS = private static final Set<String> CREATE_DATABASE_OPTIONS =
Set.of(NAME_OPTION, OWNER_OPTION, DESCRIPTION_OPTION, NO_CALLGRAPH_OPTION); Set.of(NAME_OPTION, OWNER_OPTION, DESCRIPTION_OPTION, NO_CALLGRAPH_OPTION);
private static final Set<String> COMMIT_SIGS_OPTIONS = 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> COMMIT_UPDATES_OPTIONS = Set.of();
private static final Set<String> DELETE_OPTIONS = private static final Set<String> DELETE_OPTIONS =
Set.of(MD5_OPTION, NAME_OPTION, ARCH_OPTION, COMPILER_OPTION); // one or more params required 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 ghidraURL;
private URL bsimURL; private URL bsimURL;
private String bsimURLOption; // Command-line option: bsim=.. private Map<String, String> optionValueMap = new HashMap<>();
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 Set<String> booleanOptions = new HashSet<>(); private Set<String> booleanOptions = new HashSet<>();
private GhidraApplicationLayout layout; private GhidraApplicationLayout layout;
@ -199,22 +204,8 @@ public class BSimLaunchable implements GhidraLaunchable {
private void clearParams() { private void clearParams() {
ghidraURL = null; ghidraURL = null;
bsimURL = 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(); booleanOptions.clear();
optionValueMap.clear();
} }
private BulkSignatures getBulkSignatures() private BulkSignatures getBulkSignatures()
@ -223,6 +214,7 @@ public class BSimLaunchable implements GhidraLaunchable {
if (bsimURL != null) { if (bsimURL != null) {
serverInfo = new BSimServerInfo(bsimURL); serverInfo = new BSimServerInfo(bsimURL);
} }
String connectingUserName = optionValueMap.get(USER_OPTION);
return new BulkSignatures(serverInfo, connectingUserName); return new BulkSignatures(serverInfo, connectingUserName);
} }
@ -281,6 +273,8 @@ public class BSimLaunchable implements GhidraLaunchable {
*/ */
private List<String> readOptions(String command, String[] params, int discard) { private List<String> readOptions(String command, String[] params, int discard) {
boolean sawOptions = false;
Set<String> allowedParams = ALLOWED_OPTION_MAP.get(command); Set<String> allowedParams = ALLOWED_OPTION_MAP.get(command);
if (allowedParams == null) { if (allowedParams == null) {
throw new IllegalArgumentException("Unsupported command: " + command); throw new IllegalArgumentException("Unsupported command: " + command);
@ -288,101 +282,61 @@ public class BSimLaunchable implements GhidraLaunchable {
List<String> subParams = new ArrayList<String>(); List<String> subParams = new ArrayList<String>();
for (int i = discard; i < params.length; ++i) { for (int i = discard; i < params.length; ++i) {
String option = params[i]; String optionName = params[i];
String value = null;
int ix = option.indexOf('='); if (optionName.startsWith("-")) {
if (ix > 0) { // although not prefered, allow option value to be specified as --option=value
String checkOption = option.substring(0, ix + 1); // include '=' in option name int ix = optionName.indexOf("=");
if (!GLOBAL_OPTIONS.contains(checkOption) && !allowedParams.contains(checkOption)) { if (ix > 1) {
throw new IllegalArgumentException("Unsupported option use: " + checkOption); value = optionName.substring(ix + 1);
optionName = optionName.substring(0, ix);
} }
} }
else if (option.startsWith("--")) {
if (!GLOBAL_OPTIONS.contains(option) && !allowedParams.contains(option)) { String option = optionName;
throw new IllegalArgumentException("Unsupported option use: " + option);
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; continue;
} }
if (option.startsWith(BSIM_URL_OPTION)) { sawOptions = true;
bsimURLOption = option.substring(BSIM_URL_OPTION.length()); if (!GLOBAL_OPTIONS.contains(option) && !allowedParams.contains(option)) {
throw new IllegalArgumentException("Unsupported option use: " + optionName);
} }
else if (option.startsWith(GHIDRA_URL_OPTION)) { if (!VALUE_OPTIONS.contains(option)) {
ghidraURLOption = option.substring(GHIDRA_URL_OPTION.length()); // consume option without value arg as a boolean option
} if (value != null) {
else if (option.startsWith(NAME_OPTION)) { throw new IllegalArgumentException(
nameOption = option.substring(NAME_OPTION.length()); "Unsupported option specification: " + optionName + "=");
}
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);
} }
booleanOptions.add(option);
} }
else if (option.startsWith(FILTER_OPTION)) { else if (!StringUtils.isBlank(value)) {
filterOption = option.substring(FILTER_OPTION.length()); optionValueMap.put(option, value);
}
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 { 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) { if (connectingUserName == null) {
connectingUserName = ClientUtil.getUserName(); connectingUserName = optionValueMap.put(USER_OPTION, ClientUtil.getUserName());
} }
return subParams; 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. * 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 { public void run(String[] params, TaskMonitor monitor) throws Exception, CancelledException {
clearParams();
checkRequiredParam(params, 0, "command"); checkRequiredParam(params, 0, "command");
String command = params[0]; String command = params[0];
if (!COMMAND_SET.contains(command)) { if (!COMMAND_SET.contains(command)) {
@ -420,7 +393,6 @@ public class BSimLaunchable implements GhidraLaunchable {
monitor.setCancelEnabled(true); monitor.setCancelEnabled(true);
clearParams();
List<String> subParams = readOptions(command, params, 2); List<String> subParams = readOptions(command, params, 2);
initializeApplication(command); initializeApplication(command);
@ -458,8 +430,10 @@ public class BSimLaunchable implements GhidraLaunchable {
doGenerateSigs(subParams, monitor); doGenerateSigs(subParams, monitor);
} }
else if (COMMAND_COMMIT_SIGS.equals(command)) { else if (COMMAND_COMMIT_SIGS.equals(command)) {
if (overrideOption) { // --override option specified ghidra URL
setupURLs(ghidraURLOption, urlstring); String ghidraURLOverride = optionValueMap.get(OVERRIDE_OPTION);
if (ghidraURLOverride != null) {
setupURLs(ghidraURLOverride, urlstring);
} }
else { else {
bsimURL = BSimClientFactory.deriveBSimURL(urlstring); bsimURL = BSimClientFactory.deriveBSimURL(urlstring);
@ -500,10 +474,12 @@ public class BSimLaunchable implements GhidraLaunchable {
} }
private void processSigAndUpdateOptions(String urlstring) throws MalformedURLException { private void processSigAndUpdateOptions(String urlstring) throws MalformedURLException {
String bsimURLOption = optionValueMap.get(BSIM_URL_OPTION);
String configOption = optionValueMap.get(CONFIG_OPTION);
if (configOption != null) { if (configOption != null) {
if (bsimURLOption != null) { if (bsimURLOption != null) {
throw new IllegalArgumentException( 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); setupGhidraURL(urlstring);
} }
@ -512,7 +488,7 @@ public class BSimLaunchable implements GhidraLaunchable {
} }
else { else {
throw new IllegalArgumentException( 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); String configTemplate = params.get(0);
boolean noTrackCallGraph = booleanOptions.contains(NO_CALLGRAPH_OPTION); 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()) { try (BulkSignatures bsim = getBulkSignatures()) {
bsim.createDatabase(configTemplate, nameOption, ownerOption, descOption, bsim.createDatabase(configTemplate, nameOption, ownerOption, descOption,
!noTrackCallGraph); !noTrackCallGraph);
@ -551,19 +531,20 @@ public class BSimLaunchable implements GhidraLaunchable {
private void doGenerateSigs(List<String> params, TaskMonitor monitor) private void doGenerateSigs(List<String> params, TaskMonitor monitor)
throws Exception, CancelledException { throws Exception, CancelledException {
// concurrent bsim= and config= option use already checked // concurrent --bsim and --config option use already checked
if (params.size() > 1) { if (params.size() > 1) {
throw new IllegalArgumentException("Invalid generatesigs parameter use!"); throw new IllegalArgumentException("Invalid generatesigs parameter use!");
} }
boolean commitOption = booleanOptions.contains(COMMIT_OPTION); boolean commitOption = booleanOptions.contains(COMMIT_OPTION);
boolean overwriteOption = booleanOptions.contains(OVERWRITE_OPTION); boolean overwriteOption = booleanOptions.contains(OVERWRITE_OPTION);
String configOption = optionValueMap.get(CONFIG_OPTION);
String xmlDirectory = null; String xmlDirectory = null;
if (params.size() == 1) { if (params.size() == 1) {
xmlDirectory = params.get(0); xmlDirectory = params.get(0);
if (configOption != null && commitOption) { if (configOption != null && commitOption) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Invalid option use with config= option: " + COMMIT_OPTION); "Invalid option use with " + CONFIG_OPTION + " option: " + COMMIT_OPTION);
} }
} }
else { else {
@ -588,19 +569,20 @@ public class BSimLaunchable implements GhidraLaunchable {
private void doGenerateUpdates(List<String> params, TaskMonitor monitor) private void doGenerateUpdates(List<String> params, TaskMonitor monitor)
throws Exception, CancelledException { throws Exception, CancelledException {
// concurrent bsim= and config= option use already checked // concurrent --bsim and --config option use already checked
if (params.size() > 1) { if (params.size() > 1) {
throw new IllegalArgumentException("Invalid generateupdates parameter use!"); throw new IllegalArgumentException("Invalid generateupdates parameter use!");
} }
boolean commitOption = booleanOptions.contains(COMMIT_OPTION); boolean commitOption = booleanOptions.contains(COMMIT_OPTION);
boolean overwriteOption = booleanOptions.contains(OVERWRITE_OPTION); boolean overwriteOption = booleanOptions.contains(OVERWRITE_OPTION);
String configOption = optionValueMap.get(CONFIG_OPTION);
String xmlDirectory = null; String xmlDirectory = null;
if (params.size() == 1) { if (params.size() == 1) {
xmlDirectory = params.get(0); xmlDirectory = params.get(0);
if (configOption != null && commitOption) { if (configOption != null && commitOption) {
throw new IllegalArgumentException( 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) { if (params.size() < 1) {
throw new IllegalArgumentException("Missing directory containing signature files"); 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); String xmlDirectory = params.get(0);
File dir = checkDirectory(xmlDirectory); File dir = checkDirectory(xmlDirectory);
boolean hasOverride = optionValueMap.containsKey(OVERRIDE_OPTION);
String md5Filter = optionValueMap.get(MD5_OPTION);
try (BulkSignatures bsim = getBulkSignatures()) { try (BulkSignatures bsim = getBulkSignatures()) {
bsim.sendXmlToQueryServer(dir, overrideOption ? ghidraURL : null, filterOption, bsim.sendXmlToQueryServer(dir, hasOverride ? ghidraURL : null, md5Filter, monitor);
monitor);
} }
} }
@ -678,10 +659,17 @@ public class BSimLaunchable implements GhidraLaunchable {
} }
private void fillinSingleExeSpecifier(ExeSpecifier spec) throws IllegalArgumentException { 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 (md5Option != null) {
if (!isAllNull(nameOption, archOption, compOption)) { if (!isAllNull(nameOption, archOption, compOption)) {
throw new IllegalArgumentException( 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; spec.exemd5 = md5Option;
} }
@ -691,14 +679,18 @@ public class BSimLaunchable implements GhidraLaunchable {
spec.execompname = compOption; spec.execompname = compOption;
} }
else { 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 { private void doListFunctions(List<String> params) throws IOException, LSHException {
Integer maxFunc = parsePositiveIntegerOption(MAX_FUNC_OPTION);
QueryName query = new QueryName(); QueryName query = new QueryName();
fillinSingleExeSpecifier(query.spec); fillinSingleExeSpecifier(query.spec);
if (maxFunc != null) { if (maxFunc != null) {
query.maxfunc = maxFunc; query.maxfunc = maxFunc;
} }
@ -792,17 +784,28 @@ public class BSimLaunchable implements GhidraLaunchable {
private void doListExes(List<String> params) throws IOException, LSHException { private void doListExes(List<String> params) throws IOException, LSHException {
int limit = DEFAULT_LIST_EXE_LIMIT; int limit = DEFAULT_LIST_EXE_LIMIT;
Integer limitOption = parsePositiveIntegerOption(LIMIT_OPTION);
if (limitOption != null) { if (limitOption != null) {
limit = limitOption; limit = limitOption;
} }
boolean includeLibs = booleanOptions.contains(INCLUDE_LIBS_OPTION); 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()) { try (BulkSignatures bsim = getBulkSignatures()) {
List<ExecutableRecord> exeList = bsim.getExes(limit, md5Option, nameOption, archOption, List<ExecutableRecord> exeList = bsim.getExes(limit, md5Option, nameOption, archOption,
compOption, sortColumn, includeLibs); compOption, sortColumnOption, includeLibs);
for (ExecutableRecord exeRec : exeList) { for (ExecutableRecord exeRec : exeList) {
Msg.info(this, exeRec.printRaw()); 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 * @throws LSHException if there's an error issuing the query
*/ */
private void doGetCount(List<String> params) throws IOException, LSHException { private void doGetCount(List<String> params) throws IOException, LSHException {
boolean includeFakes = booleanOptions.contains(INCLUDE_LIBS_OPTION); 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()) { try (BulkSignatures bsim = getBulkSignatures()) {
int count = bsim.getCount(md5Option, nameOption, archOption, compOption, includeFakes); int count = bsim.getCount(md5Option, nameOption, archOption, compOption, includeFakes);
System.out.println("Matching executable count: " + count); 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 * @throws LSHException if there's an error issuing the query
*/ */
private void doInstallMetadata(List<String> params) throws IOException, LSHException { 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)) { if (isAllNull(nameOption, ownerOption, descOption)) {
throw new IllegalArgumentException( throw new IllegalArgumentException("Missing one or more metadata options: " +
"Missing one or more metadata options: [name=..] [owner=..] [description=..]"); NAME_OPTION + ", " + OWNER_OPTION + ", " + DESCRIPTION_OPTION);
} }
try (BulkSignatures bsim = getBulkSignatures()) { try (BulkSignatures bsim = getBulkSignatures()) {
@ -920,30 +934,30 @@ public class BSimLaunchable implements GhidraLaunchable {
//@formatter:off //@formatter:off
System.err.println( System.err.println(
"USAGE: bsim [command] required-args... [OPTIONS...]\n" + "USAGE: bsim [command] required-args... [OPTIONS...]\n" +
" createdatabase <bsimURL> <config_template> [name=\"<name>\"] [owner=\"<owner>\"] [description=\"<text>\"] [--nocallgraph]\n" + " createdatabase <bsimURL> <config_template> [--name|-n \"<name>\"] [--owner|-o \"<owner>\"] [--description|-d \"<text>\"] [--nocallgraph]\n" +
" setmetadata <bsimURL> [name=\"<name>\"] [owner=\"<owner>\"] [description=\"<text>\"]\n" + " setmetadata <bsimURL> [--name|-n \"<name>\"] [--owner|-o \"<owner>\"] [--description|-d \"<text>\"]\n" +
" addexecategory <bsimURL> <category_name> [--date]\n" + " addexecategory <bsimURL> <category_name> [--date]\n" +
" addfunctiontag <bsimURL> <tag_name>\n" + " addfunctiontag <bsimURL> <tag_name>\n" +
" dropindex <bsimURL>\n" + " dropindex <bsimURL>\n" +
" rebuildindex <bsimURL>\n" + " rebuildindex <bsimURL>\n" +
" prewarm <bsimURL>\n" + " prewarm <bsimURL>\n" +
" generatesigs <ghidraURL> </xmldirectory> config=<config_template> [--overwrite]\n" + " generatesigs <ghidraURL> </xmldirectory> --config|-c <config_template> [--overwrite]\n" +
" generatesigs <ghidraURL> </xmldirectory> bsim=<bsimURL> [--commit] [--overwrite]\n" + " generatesigs <ghidraURL> </xmldirectory> --bsim|-b <bsimURL> [--commit] [--overwrite]\n" +
" generatesigs <ghidraURL> bsim=<bsimURL>\n" + " generatesigs <ghidraURL> --bsim|-b <bsimURL>\n" +
" commitsigs <bsimURL> </xmldirectory> [md5=<hash>] [override=<ghidraURL>]\n" + " commitsigs <bsimURL> </xmldirectory> [--md5|-m <hash>] [--override <ghidraURL>]\n" +
" generateupdates <ghidraURL> </xmldirectory> config=<config_template> [--overwrite]\n" + " generateupdates <ghidraURL> </xmldirectory> --config|-c <config_template> [--overwrite]\n" +
" generateupdates <ghidraURL> </xmldirectory> bsim=<bsimURL> [--commit] [--overwrite]\n" + " generateupdates <ghidraURL> </xmldirectory> --bsim|-b <bsimURL> [--commit] [--overwrite]\n" +
" generateupdates <ghidraURL> bsim=<bsimURL>\n" + " generateupdates <ghidraURL> --bsim|-b <bsimURL>\n" +
" commitupdates <bsimURL> </xmldirectory>\n" + " commitupdates <bsimURL> </xmldirectory>\n" +
" listexes <bsimURL> [md5=<hash>] [name=<exe_name>] [arch=<languageID>] [compiler=<cspecID>] [sortcol=<column_name>] [limit=<exe_count>] [--includelibs]\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=<hash>] [name=<exe_name>] [arch=<languageID>] [compiler=<cspecID>] [--includelibs]\n" + " getexecount <bsimURL> [--md5|-m <hash>] [--name|-n <exe_name>] [--arch|-a <languageID>] [--compiler <cspecID>] [--includelibs]\n" +
" delete <bsimURL> [md5=<hash>] [name=<exe_name> [arch=<languageID>] [compiler=<cspecID>]]\n" + " delete <bsimURL> [--md5|-m <hash>] [--name|-n <exe_name> [--arch|-a <languageID>] [--compiler <cspecID>]]\n" +
" listfuncs <bsimURL> [md5=<hash>] [name=<exe_name> [arch=<languageID>] [compiler=<cspecID>]] [--printselfsig] [--callgraph] [--printjustexe] [maxfunc=<max_count>]\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=<hash>] [name=<exe_name> [arch=<languageID>] [compiler=<cspecID>]]\n" + " dumpsigs <bsimURL> </xmldirectory> [--md5|-m <hash>] [--name|-n <exe_name> [--arch|-a <languageID>] [--compiler <cspecID>]]\n" +
"\n" + "\n" +
"Global options:\n" + "Global options:\n" +
" user=<username>\n" + " --user|-u <username>\n" +
" cert=</certfile-path>\n" + " --cert </certfile-path>\n" +
"\n" + "\n" +
"Enumerated Options:\n" + "Enumerated Options:\n" +
" <config_template> - large_32 | medium_32 | medium_64 | medium_cpool | medium_nosize \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 URL Forms (ghidraURL):\n" +
" ghidra://<hostname>[:<port>]/<repo-name>[/<folder-path>]\n" + " ghidra://<hostname>[:<port>]/<repo-name>[/<folder-path>]\n" +
" ghidra:/[<local-dirpath>/]<project-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 //@formatter:on
} }
@ -991,6 +1006,10 @@ public class BSimLaunchable implements GhidraLaunchable {
private void initializeApplication(String command) throws IOException { private void initializeApplication(String command) throws IOException {
int initType = COMMANDS_WITH_REPO_ACCESS.contains(command) ? 2 : 1; int initType = COMMANDS_WITH_REPO_ACCESS.contains(command) ? 2 : 1;
if (layout != null) { if (layout != null) {
String connectingUserName = optionValueMap.get(USER_OPTION);
String certOption = optionValueMap.get(CERT_OPTION);
initializeApplication(layout, initType, connectingUserName, certOption); 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.description.*;
import ghidra.features.bsim.query.protocol.*; import ghidra.features.bsim.query.protocol.*;
import ghidra.features.bsim.query.protocol.ResponseDelete.DeleteResult; import ghidra.features.bsim.query.protocol.ResponseDelete.DeleteResult;
import ghidra.framework.Application;
import ghidra.framework.client.ClientUtil; import ghidra.framework.client.ClientUtil;
import ghidra.framework.protocol.ghidra.GhidraURL; import ghidra.framework.protocol.ghidra.GhidraURL;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
@ -184,6 +185,10 @@ public class BulkSignatures implements AutoCloseable {
insertreq.path_override = GhidraURL.getProjectPathname(ghidraOverrideURL); insertreq.path_override = GhidraURL.getProjectPathname(ghidraOverrideURL);
} }
loadSignatureXml(file, insertreq.manage); 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) { if (insertreq.execute(querydb) == null) {
Error lastError = querydb.getLastError(); Error lastError = querydb.getLastError();
if ((lastError.category == ErrorCategory.Format) || if ((lastError.category == ErrorCategory.Format) ||
@ -646,7 +651,7 @@ public class BulkSignatures implements AutoCloseable {
establishQueryServerConnection(false); establishQueryServerConnection(false);
ExeTableOrderColumn sortEnum; ExeTableOrderColumn sortEnum;
if (sortCol != null) { if (sortCol != null) {
sortEnum = ExeTableOrderColumn.valueOf(sortCol); sortEnum = ExeTableOrderColumn.valueOf(sortCol.toUpperCase());
} }
else { else {
sortEnum = ExeTableOrderColumn.MD5; sortEnum = ExeTableOrderColumn.MD5;
@ -961,11 +966,12 @@ public class BulkSignatures implements AutoCloseable {
protected File establishTemporaryDirectory(String xmldir) throws IOException { protected File establishTemporaryDirectory(String xmldir) throws IOException {
File dir; File dir;
if (xmldir == null) { if (xmldir == null) {
String tempDirString = System.getProperty("java.io.tmpdir"); File tmpDir = Application.getUserTempDirectory();
if (tempDirString == null) { if (tmpDir == null) {
throw new IOException("Could not find temporary directory"); throw new IOException("Could not find temporary directory");
} }
dir = new File(tempDirString, "bulkinsert_xml"); dir = new File(tmpDir, "bulkinsert_xml");
deleteTemporaryDirectory(dir);
} }
else { else {
dir = new File(xmldir); dir = new File(xmldir);
@ -983,6 +989,9 @@ public class BulkSignatures implements AutoCloseable {
} }
private void deleteTemporaryDirectory(File tempDir) throws IOException { private void deleteTemporaryDirectory(File tempDir) throws IOException {
if (!tempDir.exists()) {
return;
}
File[] listFiles = tempDir.listFiles(); File[] listFiles = tempDir.listFiles();
if (listFiles == null) { if (listFiles == null) {
throw new IOException( throw new IOException(
@ -1106,6 +1115,7 @@ public class BulkSignatures implements AutoCloseable {
if (manager.numFunctions() == 0) { if (manager.numFunctions() == 0) {
Msg.warn(this, program.getDomainFile().getName() + Msg.warn(this, program.getDomainFile().getName() +
" contains no functions with signatures"); " contains no functions with signatures");
return;
} }
FileWriter fwrite = new FileWriter(file); FileWriter fwrite = new FileWriter(file);
manager.saveXml(fwrite); manager.saveXml(fwrite);

View file

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

View file

@ -3,9 +3,8 @@
@echo off @echo off
setlocal setlocal
:: Maximum heap memory may be changed if default is inadequate. This will generally be up to 1/4 of :: maximum heap memory (may be increased)
:: the physical memory available to the OS. Uncomment MAXMEM setting if non-default value is needed. set MAXMEM=2G
::set MAXMEM=2G
:: launch mode (fg, bg, debug, debug-suspend) :: launch mode (fg, bg, debug, debug-suspend)
set LAUNCH_MODE=fg 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 <pre><code class="language-bash">cd &lt;ghidra_install_dir&gt;/support
mkdir ~/bsim_sigs 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> </code></pre>
<ul> <ul>
<li>The <code>ghidra:/</code> argument is the local project which holds the analyzed binaries. <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> 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> This command does not add any signatures to the database, but it does query the database for its settings.</li>
</ul> </ul>

View file

@ -22,12 +22,12 @@ To generate the signature files, execute the following commands in a shell (adju
```bash ```bash
cd <ghidra_install_dir>/support cd <ghidra_install_dir>/support
mkdir ~/bsim_sigs 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. - 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. 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. This command does not add any signatures to the database, but it does query the database for its settings.
## Committing Signature Files ## Committing Signature Files