diff --git a/htroot/CookieTest.java b/htroot/CookieTest.java index 12d59489a..ced723be3 100644 --- a/htroot/CookieTest.java +++ b/htroot/CookieTest.java @@ -80,7 +80,7 @@ public class CookieTest { for(int i=0;i1?(nameValue[1].trim()):"","Thu, 01-Jan-99 00:00:01 GMT"); + outgoingHeader.setCookie(nameValue[0].trim(),nameValue.length>1?(nameValue[1].trim()):"","Thu, 01-Jan-99 00:00:01 GMT"); } } @@ -95,31 +95,21 @@ public class CookieTest { } else if(post.containsKey("act")&&post.get("act").equals("set_cookie")) { - String CoockieName = post.get("cookie_name").toString().trim(); - String CoockieValue = post.get("cookie_value").toString().trim(); + String cookieName = post.get("cookie_name").toString().trim(); + String cookieValue = post.get("cookie_value").toString().trim(); httpHeader outgoingHeader=new httpHeader(); - outgoingHeader.setCoockie(CoockieName,CoockieValue); + outgoingHeader.setCookie(cookieName,cookieValue); prop.setOutgoingHeader(outgoingHeader); prop.put("cookiesin",1); - prop.put("cookiesin_0_name",CoockieName); - prop.put("cookiesin_0_value",CoockieValue); + prop.put("cookiesin_0_name",cookieName); + prop.put("cookiesin_0_value",cookieValue); //header. } -Iterator it = header.entrySet().iterator(); -while(it.hasNext()) -{ - java.util.Map.Entry e = (Entry) it.next(); - System.out.println(""+e.getKey()+" : "+e.getValue()); - if(e.getKey().equals("Cookie")) - { - prop.put("cookiesout",1); - prop.put("cookiesout_0_string",e.getValue().toString().replaceAll(";",";
")); - } -} - + prop.put("cookiesout",1); + prop.put("cookiesout_0_string", header.getHeaderCookies().replaceAll(";",";
")); return prop; } diff --git a/htroot/User.html b/htroot/User.html index 755b120aa..814a69ad9 100644 --- a/htroot/User.html +++ b/htroot/User.html @@ -17,7 +17,7 @@ Password:
:: You are currently logged in as #[username]#.
-(Identified by #(identified-by)#IP::Username/Password#(/identified-by)#)
+(Identified by #(identified-by)#IP::Username/Password::Cookie#(/identified-by)#)
diff --git a/htroot/User.java b/htroot/User.java index 3751ea4a8..cef0232ca 100644 --- a/htroot/User.java +++ b/htroot/User.java @@ -57,7 +57,17 @@ import de.anomic.server.serverSwitch; public class User{ - + private static String getLoginToken(String cookies){ + String[] cookie=cookies.split(";"); //TODO: Mozilla uses + String[] pair; + for(int i=0;i 0){ - prop.put("logged-in_limit", 1); - long limit=entry.getTimeLimit(); - long used=entry.getTimeUsed(); - prop.put("logged-in_limit_timelimit", limit); - prop.put("logged-in_limit_timeused", used); - int percent=0; - if(limit!=0 && used != 0) - percent=(int)((float)used/(float)limit*100); - prop.put("logged-in_limit_percent", percent/3); - prop.put("logged-in_limit_percent2", (100-percent)/3); - } + prop.put("logged-in", 1); + prop.put("logged-in_username", entry.getUserName()); + if(entry.getTimeLimit() > 0){ + prop.put("logged-in_limit", 1); + long limit=entry.getTimeLimit(); + long used=entry.getTimeUsed(); + prop.put("logged-in_limit_timelimit", limit); + prop.put("logged-in_limit_timeused", used); + int percent=0; + if(limit!=0 && used != 0) + percent=(int)((float)used/(float)limit*100); + prop.put("logged-in_limit_percent", percent/3); + prop.put("logged-in_limit_percent2", (100-percent)/3); + } //logged in via static Password }else if(sb.verifyAuthentication(header, true)){ prop.put("logged-in", 2); - //not logged in + //identified via form-login + //TODO: this does not work for a static admin, yet. + }else if(post != null && post.containsKey("username") && post.containsKey("password")){ + //entry=sb.userDB.passwordAuth((String)post.get("username"), (String)post.get("password"), (String)header.get("CLIENTIP", "xxxxxx")); + entry=sb.userDB.passwordAuth((String)post.get("username"), (String)post.get("password")); + if(entry != null){ + //set a random token in a cookie + String cookie=sb.userDB.getCookie(entry); + httpHeader outgoingHeader=new httpHeader(); + outgoingHeader.setCookie("login", cookie); + prop.setOutgoingHeader(outgoingHeader); + + prop.put("logged-in", 1); + prop.put("logged-in_identified-by", 1); + prop.put("logged-in_username", entry.getUserName()); + if(post.containsKey("returnto")){ + prop.put("LOCATION", (String)post.get("returnto")); + } + } } + if(post!= null && entry != null){ if(post.containsKey("changepass")){ prop.put("status", 1); //password @@ -131,9 +158,9 @@ public class User{ if(post!=null && post.containsKey("logout")){ prop.put("logged-in",0); if(entry != null){ - entry.logout(((String)header.get("CLIENTIP", "xxxxxx"))); + entry.logout(((String)header.get("CLIENTIP", "xxxxxx")), getLoginToken(header.getHeaderCookies())); //todo: logout cookie } - if(sb.verifyAuthentication(header, true)){ + if(sb.verifyAuthentication(header, true)){ //XXX: for httpauth userDB user, too? prop.put("AUTHENTICATE","admin log-in"); } } diff --git a/source/de/anomic/data/userDB.java b/source/de/anomic/data/userDB.java index b111a8d80..ddf5bd071 100644 --- a/source/de/anomic/data/userDB.java +++ b/source/de/anomic/data/userDB.java @@ -52,6 +52,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; +import java.util.Random; import de.anomic.kelondro.kelondroBase64Order; import de.anomic.kelondro.kelondroDyn; @@ -69,6 +70,7 @@ public final class userDB { private final File userTableFile; private final int bufferkb; private HashMap ipUsers = new HashMap(); + private HashMap cookieUsers = new HashMap(); public userDB(File userTableFile, int bufferkb) { this.userTableFile = userTableFile; @@ -181,6 +183,9 @@ public final class userDB { * it tests both userDB and oldstyle adminpw. * @param auth the http-headerline for authorisation */ + public boolean hasAdminRight(String auth, String ip, String cookies){ + return hasAdminRight(auth); + } public boolean hasAdminRight(String auth){ plasmaSwitchboard sb=plasmaSwitchboard.getSwitchboard(); String adminAccountBase64MD5 = sb.getConfig("adminAccountBase64MD5", ""); @@ -241,7 +246,7 @@ public final class userDB { return null; } entry.updateLastAccess(false); - this.ipUsers.put(ip, entry.getUserName()); + this.ipUsers.put(ip, entry.getUserName()); //XXX: This is insecure. TODO: use cookieauth return entry; } public Entry md5Auth(String user, String md5){ @@ -256,6 +261,17 @@ public final class userDB { } return entry; } + public Entry cookieAuth(String cookieString){ + if(cookieUsers.containsKey(cookieString)) + return (Entry) cookieUsers.get(cookieString); + return null; + } + public String getCookie(Entry entry){ + Random r = new Random(); + String token = Long.toString(Math.abs(r.nextLong()), 36); + cookieUsers.put(token, entry); + return token; + } public class Entry { public static final String MD5ENCODED_USERPWD_STRING = "MD5_user:pwd"; @@ -473,6 +489,12 @@ public final class userDB { public boolean isLoggedOut(){ return (this.mem.containsKey(LOGGED_OUT)?((String)this.mem.get(LOGGED_OUT)).equals("true"):false); } + public void logout(String ip, String cookieString){ + logout(ip); + if(cookieUsers.containsKey(cookieString)){ + cookieUsers.remove(cookieString); + } + } public void logout(String ip){ try{ setProperty(LOGGED_OUT, "true"); diff --git a/source/de/anomic/http/httpHeader.java b/source/de/anomic/http/httpHeader.java index eb232cc27..ac1274f4c 100644 --- a/source/de/anomic/http/httpHeader.java +++ b/source/de/anomic/http/httpHeader.java @@ -73,6 +73,7 @@ import java.util.Properties; import java.util.TimeZone; import java.util.TreeMap; import java.util.Vector; +import java.util.Map.Entry; import de.anomic.server.serverCore; import de.anomic.server.logging.serverLog; @@ -776,15 +777,15 @@ public final class httpHeader extends TreeMap implements Map { * Patch BEGIN: * Name: Header Property Patch * Date: Fri. 13.01.2006 - * Description: Makes possible to send header properties such as coockies back to the client. + * Description: Makes possible to send header properties such as cookies back to the client. * Part 1 of 5 * Questions: sergej.z@list.ru */ /** * Holds header properties */ - //Since properties such as coockies can be multiple, we cannot use HashMap here. We have to use Vector. - private Vector coockies=new Vector(); + //Since properties such as cookies can be multiple, we cannot use HashMap here. We have to use Vector. + private Vector cookies=new Vector(); /** * * Implementation of Map.Entry. Structure that hold two values - exactly what we need! @@ -802,89 +803,102 @@ public final class httpHeader extends TreeMap implements Map { /** * Sets Cookie on the client machine. * - * @param name: Coockie name - * @param value: Coockie value - * @param expires: when should this coockie be autmatically deleted. If null - coockie will stay forever - * @param path: Path the coockie belongs to. Default - "/". Can be null. + * @param name: Cookie name + * @param value: Cookie value + * @param expires: when should this cookie be autmatically deleted. If null - cookie will stay forever + * @param path: Path the cookie belongs to. Default - "/". Can be null. * @param domain: Domain this cookie belongs to. Default - domain name. Can be null. - * @param secure: If true coockie will be send only over safe connection such as https + * @param secure: If true cookie will be send only over safe connection such as https * Further documentation at docs.sun.com */ - public void setCoockie(String name, String value, String expires, String path, String domain, boolean secure) + public void setCookie(String name, String value, String expires, String path, String domain, boolean secure) { /* * TODO:Here every value can be validated for correctness if needed * For example semicolon should be not in any of the values * However an exception in this case would be an overhead IMHO. */ - String coockieString=name+"="+value+";"; + String cookieString=name+"="+value+";"; if(expires!=null) - coockieString+=" expires="+expires+";"; + cookieString+=" expires="+expires+";"; if(path!=null) - coockieString+=" path="+path+";"; + cookieString+=" path="+path+";"; if(domain!=null) - coockieString+=" domain="+domain+";"; + cookieString+=" domain="+domain+";"; if(secure) - coockieString+=" secure;"; - coockies.add(new Entry("Set-Cookie",coockieString)); + cookieString+=" secure;"; + cookies.add(new Entry("Set-Cookie",cookieString)); } /** * Sets Cookie on the client machine. * - * @param name: Coockie name - * @param value: Coockie value - * @param expires: when should this coockie be autmatically deleted. If null - coockie will stay forever - * @param path: Path the coockie belongs to. Default - "/". Can be null. + * @param name: Cookie name + * @param value: Cookie value + * @param expires: when should this cookie be autmatically deleted. If null - cookie will stay forever + * @param path: Path the cookie belongs to. Default - "/". Can be null. * @param domain: Domain this cookie belongs to. Default - domain name. Can be null. * - * Note: this coockie will be sent over each connection independend if it is safe connection or not. + * Note: this cookie will be sent over each connection independend if it is safe connection or not. * Further documentation at docs.sun.com */ - public void setCoockie(String name, String value, String expires, String path, String domain) + public void setCookie(String name, String value, String expires, String path, String domain) { - setCoockie( name, value, expires, path, domain, false); + setCookie( name, value, expires, path, domain, false); } /** * Sets Cookie on the client machine. * - * @param name: Coockie name - * @param value: Coockie value - * @param expires: when should this coockie be autmatically deleted. If null - coockie will stay forever - * @param path: Path the coockie belongs to. Default - "/". Can be null. + * @param name: Cookie name + * @param value: Cookie value + * @param expires: when should this cookie be autmatically deleted. If null - cookie will stay forever + * @param path: Path the cookie belongs to. Default - "/". Can be null. * - * Note: this coockie will be sent over each connection independend if it is safe connection or not. + * Note: this cookie will be sent over each connection independend if it is safe connection or not. * Further documentation at docs.sun.com */ - public void setCoockie(String name, String value, String expires, String path) + public void setCookie(String name, String value, String expires, String path) { - setCoockie( name, value, expires, path, null, false); + setCookie( name, value, expires, path, null, false); } /** * Sets Cookie on the client machine. * - * @param name: Coockie name - * @param value: Coockie value - * @param expires: when should this coockie be autmatically deleted. If null - coockie will stay forever + * @param name: Cookie name + * @param value: Cookie value + * @param expires: when should this cookie be autmatically deleted. If null - cookie will stay forever * - * Note: this coockie will be sent over each connection independend if it is safe connection or not. + * Note: this cookie will be sent over each connection independend if it is safe connection or not. * Further documentation at docs.sun.com */ - public void setCoockie(String name, String value, String expires) + public void setCookie(String name, String value, String expires) { - setCoockie( name, value, expires, null, null, false); + setCookie( name, value, expires, null, null, false); } /** * Sets Cookie on the client machine. * - * @param name: Coockie name - * @param value: Coockie value + * @param name: Cookie name + * @param value: Cookie value * - * Note: this coockie will be sent over each connection independend if it is safe connection or not. This coockie never expires + * Note: this cookie will be sent over each connection independend if it is safe connection or not. This cookie never expires * Further documentation at docs.sun.com */ - public void setCoockie(String name, String value ) + public void setCookie(String name, String value ) { - setCoockie( name, value, null, null, null, false); + setCookie( name, value, null, null, null, false); + } + public String getHeaderCookies(){ + Iterator it = this.entrySet().iterator(); + while(it.hasNext()) + { + java.util.Map.Entry e = (java.util.Map.Entry) it.next(); + System.out.println(""+e.getKey()+" : "+e.getValue()); + if(e.getKey().equals("Cookie")) + { + return e.getValue().toString(); + } + } + return ""; } /** * Returns an iterator within all properties can be reached. @@ -903,7 +917,7 @@ public final class httpHeader extends TreeMap implements Map { */ public Iterator getCookies() { - return coockies.iterator(); + return cookies.iterator(); } /* * Patch END: diff --git a/source/de/anomic/http/httpdFileHandler.java b/source/de/anomic/http/httpdFileHandler.java index fca29816d..b640e631b 100644 --- a/source/de/anomic/http/httpdFileHandler.java +++ b/source/de/anomic/http/httpdFileHandler.java @@ -318,11 +318,7 @@ public final class httpdFileHandler extends httpdAbstractHandler implements http if ((path.substring(0,(pos==-1)?path.length():pos)).endsWith("_p") && (adminAccountBase64MD5.length() != 0)) { // authentication required - //FIXME: Form-Login is broken, until the Auth is fixed. - //ipAuth is too insecure, if the users uses a proxy. - //TODO: cookieAuth or something like this. - userDB.Entry entry=null; //sb.userDB.ipAuth(conProp.getProperty(httpHeader.CONNECTION_PROP_CLIENTIP)); - if( (entry != null && entry.hasAdminRight()) || (authorization != null && sb.userDB.hasAdminRight(authorization)) ){ + if( (authorization != null && sb.userDB.hasAdminRight(authorization, conProp.getProperty("CLIENTIP"), requestHeader.getHeaderCookies()))){ //Authentication successful. remove brute-force flag serverCore.bfHost.remove(conProp.getProperty("CLIENTIP")); }else if (authorization == null) {