Hi Luca,
I've been watching for a while but have now taken the plunge using orientdb with a java app. Its a nice piece of work, well done and thank you!
I'm a little uneasy with plain text passwords in orientdb-server-config.xml and propose some minor changes in the current dev branch. I'm also a little uneasy about use of unencrypted binary and text sockets for the server, but I can see how you expect a user to manage their own SSL layer, or use OpenVPN on your commerical service, which I don't know much about.
You already have the encryption machinery in the code so what I've added is basically:
1. a passphrase hasher invoked by starting ./server.sh with a "-p" argument (only for the linux script). The server is started and asks twice for a passphrase, then displays your existing digest2String SHA-256 hash, before quitting. The user pastes the hash into the pass value in the xml config file.
2. a request for the root passphrase on server startup and shutdown. At least then the jvm instance invocation is somewhat secure. This will present a problem when automated spawning of instances, which I'm not doing just at the moment.
3. the same hash-based authentication when a client tries to log into the server over the http socket. The password is still transmitted plain, but at least it is stored in the xml as a hash.
I noticed in current git repo (yesterday), in orientdb-server-config.xml you did not have the root user, perhaps you add that separately when building releases, so I've added:
<!-- Default root password is "root" -->
<user resources="*" password="4813494D137E1631BBA301D5ACAB6E7BB7AA74CE1185D456565EF51D737677B2" name="root"/>
<user resources="connect,server.listDatabases" password="guest" name="guest"/>
The password is just the hash of the string "root" as a default and OServerMain checks if this has been changed and aborts if not, forcing the user to change it.
In bin/server.sh I've simply added "$@" right at the end so that the -p switch can be transmitted to
java -server $JAVA_OPTS $JAVA_OPTS_SCRIPT $ORIENTDB_SETTINGS -Djava.util.logging.config.file="$LOG_FILE" -Dorientdb.config.file="$CONFIG_FILE" -Dorientdb.www.path="$WWW_PATH" -Dorientdb.build.number="@BUILD@" - >cp "$ORIENTDB_HOME/lib/orientdb-server-@VERSION@.jar:$ORIENTDB_HOME/lib/*" com.orientechnologies.orient.server.OServerMain "$@"
Most changes are in OServerMain where I've modified the main function and added some helpers (importing OSecurityManager):
public static void main(final String[] args) throws Exception {
if (args.length > 0 && args[0].trim().startsWith("-p"))
{
System.out.println("OrientDB server passphrase generator");
System.out.print("Enter passphrase : ");
char[] chars1 = System.console().readPassword();
String input1 = new String(chars1);
System.out.print("Repeat passphrase : ");
char[] chars2 = System.console().readPassword();
String input2 = new String(chars2);
if (input1 == null || input2 == null)
{
System.out.println("No input received.");
System.exit(1);
}
else if (!input1.equals(input2))
{
System.out.println("Phrases do not match, try again.");
System.exit(1);
}
System.out.println
(
"The hash is : "
+ OSecurityManager.instance().digest2String(input1)
);
System.exit(0);
}
OServerMain.create().startup();
String correct = server().getUser("root").password;
// Default hash of "root"
String defaultPhrase =
"4813494D137E1631BBA301D5ACAB6E7B"
+ "B7AA74CE1185D456565EF51D737677B2";
if (correct.equals(defaultPhrase))
{
String linesep = System.getProperty("line.separator");
System.out.println
(
linesep + linesep
+ "Passphrase has not been changed from default."
+ linesep
+ "Restart server with -p switch to set new passphrase."
+ linesep
+ "A longer phrase with alphanumerics enhances security."
);
System.exit(1);
}
requestRootPassPhrase();
// The string input could now be retained as a
// key for data encryption
server().activate();
}
public static void requestRootPassPhrase()
throws Exception
{
System.out.println();
System.out.print("Enter root passphrase: ");
char[] chars = System.console().readPassword();
String input = new String(chars);
if (grantAuthority("root", input))
{
System.out.println("Passphrase OK.");
}
else
{
System.out.println("Passphrase incorrect.");
System.exit(1);
}
}
/**
* Grant authority by comparing the stored hash of the correct password
* against the given string.
*
* @param iUserName
* Username to authenticate
* @param iPassword
* Password in clear
* @return true if authentication is ok, otherwise false
*/
public static boolean grantAuthority
(
String iUserName,
String iPassword
)
throws Exception
{
if (server() == null) create();
String correct = server().getUser(iUserName).password;
String hashed =
OSecurityManager
.instance()
.digest2String
(
iPassword
);
if (hashed.equals(correct)) return true;
return false;
}
In OServer I just replaced this lineif (user != null && (iPassword == null || user.password.equals(iPassword))) {I'm happy to commit to the repo, or else here are some ideas for getting rid of plain passwords from the xml with minimal pain.
with this
if (user != null && (iPassword == null || OServerMain.grantAuthority(iUserName, iPassword))) {
finally, I've inserted this call to the OServerMain request at the top of the try block in OServerShutdown.main
OServerMain.requestRootPassPhrase();
System.out.println("Sending shutdown command to remote OrientDB Server instance...");
Cheers
hoogs --
---
You received this message because you are subscribed to the Google Groups "OrientDB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to orient-databa...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.