Navigation Menu

Skip to content

Commit

Permalink
tweak Jetty credentials to work with YaCy UserDB
Browse files Browse the repository at this point in the history
- user entry in UserDB with admin right can login to access protected pages
- dto. admin user, choosen username is stored in conf (adminAccountUserName=)
  • Loading branch information
reger committed Dec 27, 2013
1 parent 7d6b34a commit 65a2f3d
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 51 deletions.
1 change: 1 addition & 0 deletions defaults/yacy.init
Expand Up @@ -384,6 +384,7 @@ use_proxyAccounts=true
#adminAccount=admin:mysecretpassword
adminAccount=
adminAccountBase64MD5=
adminAccountUserName=admin

# special access handling for users from localhost:
# access from localhost may be granted with administration authority
Expand Down
1 change: 1 addition & 0 deletions htroot/ConfigAccounts_p.java
Expand Up @@ -67,6 +67,7 @@ public static serverObjects respond(@SuppressWarnings("unused") final RequestHea
// check passed. set account:
env.setConfig(SwitchboardConstants.ADMIN_ACCOUNT_B64MD5, Digest.encodeMD5Hex(Base64Order.standardCoder.encodeString(user + ":" + pw1)));
env.setConfig("adminAccount", "");
env.setConfig("adminAccountUserName",user);
}

if (localhostAccess) {
Expand Down
1 change: 1 addition & 0 deletions htroot/SettingsAck_p.java
Expand Up @@ -94,6 +94,7 @@ public static serverObjects respond(final RequestHeader header, final serverObje
// check passed. set account:
env.setConfig(SwitchboardConstants.ADMIN_ACCOUNT_B64MD5, Digest.encodeMD5Hex(Base64Order.standardCoder.encodeString(user + ":" + pw1)));
env.setConfig("adminAccount", "");
env.setConfig("adminAccountUserName", user);
prop.put("info", "5");//admin account changed
prop.putHTML("info_user", user);
return prop;
Expand Down
4 changes: 2 additions & 2 deletions source/net/yacy/http/Jetty8YaCySecurityHandler.java
Expand Up @@ -31,6 +31,7 @@

import net.yacy.cora.document.id.MultiProtocolURL;
import net.yacy.cora.protocol.Domains;
import net.yacy.data.UserDB.AccessRight;
import net.yacy.search.Switchboard;

import org.eclipse.jetty.http.HttpSchemes;
Expand Down Expand Up @@ -189,13 +190,12 @@ protected RoleInfo prepareConstraintInfo(String pathInContext, Request request)
protectedPage = pathInContext.startsWith("/solr/") || pathInContext.startsWith("/gsa/");
}
//final boolean accountEmpty = adminAccountBase64MD5.length() == 0;
//final boolean yacyBot = request.getHeader("User-Agent").startsWith("yacybot");

if (protectedPage) { // TODO: none public site
if (!grantedForLocalhost) {
RoleInfo roleinfo = new RoleInfo();
roleinfo.setChecked(true); // RoleInfo.setChecked() : in Jetty this means - marked to have any security constraint
roleinfo.addRole("admin"); //YaCyLoginService assigns "admin" role to admin user
roleinfo.addRole(AccessRight.ADMIN_RIGHT.toString()); // use AccessRights as role
return roleinfo;
} // can omit else, as if grantedForLocalhost==true no constraint applies
// TODO: is this correct or adminAccountBase64MD5 not empty check neccessary ?
Expand Down
62 changes: 36 additions & 26 deletions source/net/yacy/http/YaCyLegacyCredential.java
Expand Up @@ -35,49 +35,59 @@
*/
public class YaCyLegacyCredential extends Credential {

private static final long serialVersionUID = -3527894085562480001L;
private String hash;
private String foruser; // remember the user as YaCy credential is username:pwd (not just pwd)

/**
* internal hash function
* @param clear password
* @return hash string
*/
private static String calcHash(String pw) {
return Digest.encodeMD5Hex(Base64Order.standardCoder.encodeString(pw));
}
private static final long serialVersionUID = -3527894085562480001L;
private String hash;
private String foruser; // remember the user as YaCy credential is username:pwd (not just pwd)
private boolean isBase64enc; // remember hash encoding false = encodeMD5Hex(usr:pwd) ; true = encodeMD5Hex(Base64Order.standardCoder.encodeString(usr:pw))

@Override
public boolean check(Object credentials) {
if(credentials instanceof String) {
final String pw = (String) credentials;
return calcHash(foruser+":"+pw).equals(this.hash);
}
/**
* internal hash function
*
* @param clear password
* @return hash string
*/
private static String calcHash(String pw) {
return Digest.encodeMD5Hex(Base64Order.standardCoder.encodeString(pw));
}

@Override
public boolean check(Object credentials) {
if (credentials instanceof String) {
final String pw = (String) credentials;
if (isBase64enc) { // for adminuser
return calcHash(foruser + ":" + pw).equals(this.hash);
} else { // for user
return Digest.encodeMD5Hex(foruser + ":" + pw).equals(this.hash);
}
}
throw new UnsupportedOperationException();
}
}

/**
* create Credential object from config file hash
* @param configHash hash as in config file
* @param configHash hash as in config file hash(adminuser:pwd)
* @return
*/
public static Credential getCredentialsFromConfig(String user, String configHash) {
public static Credential getCredentialsFromConfig(String username, String configHash) {
YaCyLegacyCredential c = new YaCyLegacyCredential();
c.foruser=user;
c.foruser=username;
c.isBase64enc=true;
c.hash = configHash;
return c;
}

/**
* create Credential object from password
* @param password
* @param username
* @param configHash encodeMD5Hex("user:pwd") as stored in UserDB
* @return
*/
public static Credential getCredentials(String user, String password) {
public static Credential getCredentials(String username, String configHash) {
YaCyLegacyCredential c = new YaCyLegacyCredential();
c.foruser=user;
c.hash = calcHash(user + ":" + password);
c.foruser=username;
c.isBase64enc = false;
c.hash = configHash;
//c.hash = calcHash(user + ":" + password);
return c;
}

Expand Down
68 changes: 45 additions & 23 deletions source/net/yacy/http/YaCyLoginService.java
Expand Up @@ -28,6 +28,8 @@
import java.security.Principal;

import javax.security.auth.Subject;
import net.yacy.data.UserDB.AccessRight;
import net.yacy.data.UserDB.Entry;

import net.yacy.search.Switchboard;
import net.yacy.search.SwitchboardConstants;
Expand All @@ -42,29 +44,49 @@
*/
public class YaCyLoginService extends MappedLoginService {

@Override
protected UserIdentity loadUser(String username) {
/*if(username.equals("admin"))*/ {
// TODO: implement legacy credentials
final Switchboard sb = Switchboard.getSwitchboard();
final String adminAccountBase64MD5 = sb.getConfig(SwitchboardConstants.ADMIN_ACCOUNT_B64MD5, "");
// in YaCy the credential hash is composed of username:pwd so the username is needed to create valid credential
// not just the password (as usually in Jetty). As the accountname for the std. adminuser is not stored a useridentity
// is created for current user (and the pwd checked against the stored username:pwd setting)
Credential credential = YaCyLegacyCredential.getCredentialsFromConfig(username, adminAccountBase64MD5);
// TODO: YaCy user:pwd hashes should longterm likely be switched to separable username + pwd-hash entries
// and/or the standard admin account username shuld be fix = "admin"

Principal userPrincipal = new MappedLoginService.KnownUser(username, credential);
Subject subject = new Subject();
subject.getPrincipals().add(userPrincipal);
subject.getPrivateCredentials().add(credential);
subject.setReadOnly();
IdentityService is = getIdentityService();
return is.newUserIdentity(subject, userPrincipal, new String[]{"admin"});
}
// return null;
}
@Override
protected UserIdentity loadUser(String username) {

// TODO: implement legacy credentials
final Switchboard sb = Switchboard.getSwitchboard();
String adminuser = sb.getConfig("adminAccount", "admin");
if (username.equals(adminuser)) {
final String adminAccountBase64MD5 = sb.getConfig(SwitchboardConstants.ADMIN_ACCOUNT_B64MD5, "");
// in YaCy the credential hash is composed of username:pwd so the username is needed to create valid credential
// not just the password (as usually in Jetty). As the accountname for the std. adminuser is not stored a useridentity
// is created for current user (and the pwd checked against the stored username:pwd setting)
Credential credential = YaCyLegacyCredential.getCredentialsFromConfig(username, adminAccountBase64MD5);
// TODO: YaCy user:pwd hashes should longterm likely be switched to separable username + pwd-hash entries
// and/or the standard admin account username shuld be fix = "admin"

Principal userPrincipal = new MappedLoginService.KnownUser(username, credential);
Subject subject = new Subject();
subject.getPrincipals().add(userPrincipal);
subject.getPrivateCredentials().add(credential);
subject.setReadOnly();
IdentityService is = getIdentityService();
return is.newUserIdentity(subject, userPrincipal, new String[]{AccessRight.ADMIN_RIGHT.toString()});
} else { // get user data from UserDB
Entry user = sb.userDB.getEntry(username);
if (user != null) {
String[] role;
if (user.hasRight(AccessRight.ADMIN_RIGHT)) {
role = new String[]{AccessRight.ADMIN_RIGHT.toString()};

Credential credential = YaCyLegacyCredential.getCredentials(username, user.getMD5EncodedUserPwd());
Principal userPrincipal = new MappedLoginService.KnownUser(username, credential);
Subject subject = new Subject();
subject.getPrincipals().add(userPrincipal);
subject.getPrivateCredentials().add(credential);
subject.setReadOnly();
IdentityService is = getIdentityService();

return is.newUserIdentity(subject, userPrincipal, role);
}
}
}
return null;
}

@Override
protected void loadUsers() throws IOException {
Expand Down

0 comments on commit 65a2f3d

Please sign in to comment.