mirror of
				https://github.com/gyurix1968/guacamole-client.git
				synced 2025-10-31 09:03:21 +00:00 
			
		
		
		
	Removed all files now part of other repos, moved default webapp source up
This commit is contained in:
		| @@ -0,0 +1,318 @@ | ||||
|  | ||||
| package net.sourceforge.guacamole.net.authentication.basic; | ||||
|  | ||||
| /* | ||||
|  *  Guacamole - Clientless Remote Desktop | ||||
|  *  Copyright (C) 2010  Michael Jumper | ||||
|  * | ||||
|  *  This program is free software: you can redistribute it and/or modify | ||||
|  *  it under the terms of the GNU Affero General Public License as published by | ||||
|  *  the Free Software Foundation, either version 3 of the License, or | ||||
|  *  (at your option) any later version. | ||||
|  * | ||||
|  *  This program is distributed in the hope that it will be useful, | ||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *  GNU Affero General Public License for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU Affero General Public License | ||||
|  *  along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| import java.io.File; | ||||
| import java.io.IOException; | ||||
| import java.security.MessageDigest; | ||||
| import java.security.NoSuchAlgorithmException; | ||||
| import java.util.Collections; | ||||
| import java.util.HashMap; | ||||
| import java.util.Map; | ||||
| import net.sourceforge.guacamole.GuacamoleException; | ||||
| import net.sourceforge.guacamole.net.GuacamoleProperties; | ||||
| import org.xml.sax.Attributes; | ||||
| import org.xml.sax.SAXException; | ||||
| import org.xml.sax.XMLReader; | ||||
| import org.xml.sax.helpers.DefaultHandler; | ||||
| import org.xml.sax.helpers.XMLReaderFactory; | ||||
|  | ||||
| public class BasicFileAuthenticationProvider implements BasicLogin.AuthenticationProvider { | ||||
|  | ||||
|     private long mappingTime; | ||||
|     private Map<String, AuthInfo> mapping; | ||||
|  | ||||
|     private File getUserMappingFile() throws GuacamoleException { | ||||
|  | ||||
|         // Get user mapping filename | ||||
|         String filename = GuacamoleProperties.getProperty("basic-user-mapping"); | ||||
|         if (filename == null) | ||||
|             return null; | ||||
|  | ||||
|         return new File(filename); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public synchronized void init() throws GuacamoleException { | ||||
|  | ||||
|         // Get user mapping file | ||||
|         File mapFile = getUserMappingFile(); | ||||
|         if (mapFile == null) | ||||
|             throw new GuacamoleException("Missing \"basic-user-mapping\" parameter required for basic login."); | ||||
|  | ||||
|         // Parse document | ||||
|         try { | ||||
|  | ||||
|             BasicUserMappingContentHandler contentHandler = new BasicUserMappingContentHandler(); | ||||
|  | ||||
|             XMLReader parser = XMLReaderFactory.createXMLReader(); | ||||
|             parser.setContentHandler(contentHandler); | ||||
|             parser.parse(mapFile.getAbsolutePath()); | ||||
|  | ||||
|             mappingTime = mapFile.lastModified(); | ||||
|             mapping = contentHandler.getUserMapping(); | ||||
|  | ||||
|         } | ||||
|         catch (IOException e) { | ||||
|             throw new GuacamoleException("Error reading basic user mapping file.", e); | ||||
|         } | ||||
|         catch (SAXException e) { | ||||
|             throw new GuacamoleException("Error parsing basic user mapping XML.", e); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public BasicLogin.AuthorizedConfiguration getAuthorizedConfiguration(String username, String password) throws GuacamoleException { | ||||
|  | ||||
|         // Check mapping file mod time | ||||
|         File userMappingFile = getUserMappingFile(); | ||||
|         if (userMappingFile.exists() && mappingTime < userMappingFile.lastModified()) { | ||||
|  | ||||
|             // If modified recently, gain exclusive access and recheck | ||||
|             synchronized (this) { | ||||
|                 if (userMappingFile.exists() && mappingTime < userMappingFile.lastModified()) | ||||
|                     init(); // If still not up to date, re-init | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         AuthInfo info = mapping.get(username); | ||||
|         if (info != null && info.validate(username, password)) | ||||
|             return new BasicLogin.AuthorizedConfiguration( | ||||
|                 info.getProtocol(), | ||||
|                 info.getHostname(), | ||||
|                 info.getPort(), | ||||
|                 info.getPassword() | ||||
|             ); | ||||
|  | ||||
|         return null; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public static class AuthInfo { | ||||
|  | ||||
|         public static enum Encoding { | ||||
|             PLAIN_TEXT, | ||||
|             MD5 | ||||
|         } | ||||
|  | ||||
|         private String auth_username; | ||||
|         private String auth_password; | ||||
|         private Encoding auth_encoding; | ||||
|  | ||||
|         private String protocol; | ||||
|         private String hostname; | ||||
|         private int port; | ||||
|         private String password; | ||||
|  | ||||
|         public AuthInfo(String auth_username, String auth_password, Encoding auth_encoding) { | ||||
|             this.auth_username = auth_username; | ||||
|             this.auth_password = auth_password; | ||||
|             this.auth_encoding = auth_encoding; | ||||
|         } | ||||
|  | ||||
|         private static final char HEX_CHARS[] = { | ||||
|             '0', '1', '2', '3', '4', '5', '6', '7', | ||||
|             '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' | ||||
|         }; | ||||
|  | ||||
|         public static String getHexString(byte[] bytes) { | ||||
|  | ||||
|             if (bytes == null) | ||||
|                 return null; | ||||
|  | ||||
|             StringBuilder hex = new StringBuilder(2 * bytes.length); | ||||
|             for (byte b : bytes) { | ||||
|                 hex.append(HEX_CHARS[(b & 0xF0) >> 4]) | ||||
|                    .append(HEX_CHARS[(b & 0x0F)     ]); | ||||
|             } | ||||
|  | ||||
|             return hex.toString(); | ||||
|  | ||||
|         } | ||||
|  | ||||
|  | ||||
|         public boolean validate(String username, String password) { | ||||
|  | ||||
|             // If username matches | ||||
|             if (username != null && password != null && username.equals(auth_username)) { | ||||
|  | ||||
|                 switch (auth_encoding) { | ||||
|  | ||||
|                     case PLAIN_TEXT: | ||||
|  | ||||
|                         // Compare plaintext | ||||
|                         return password.equals(auth_password); | ||||
|  | ||||
|                     case MD5: | ||||
|  | ||||
|                         // Compare hashed password | ||||
|                         try { | ||||
|                             MessageDigest digest = MessageDigest.getInstance("MD5"); | ||||
|                             String hashedPassword = getHexString(digest.digest(password.getBytes())); | ||||
|                             return hashedPassword.equals(auth_password.toUpperCase()); | ||||
|                         } | ||||
|                         catch (NoSuchAlgorithmException e) { | ||||
|                             throw new UnsupportedOperationException("Unexpected lack of MD5 support.", e); | ||||
|                         } | ||||
|  | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|  | ||||
|             return false; | ||||
|  | ||||
|         } | ||||
|  | ||||
|         public String getHostname() { | ||||
|             return hostname; | ||||
|         } | ||||
|  | ||||
|         public String getPassword() { | ||||
|             return password; | ||||
|         } | ||||
|  | ||||
|         public int getPort() { | ||||
|             return port; | ||||
|         } | ||||
|  | ||||
|         public String getProtocol() { | ||||
|             return protocol; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
|     private static class BasicUserMappingContentHandler extends DefaultHandler { | ||||
|  | ||||
|         private Map<String, AuthInfo> authMapping = new HashMap<String, AuthInfo>(); | ||||
|  | ||||
|         public Map<String, AuthInfo> getUserMapping() { | ||||
|             return Collections.unmodifiableMap(authMapping); | ||||
|         } | ||||
|  | ||||
|         private AuthInfo current; | ||||
|  | ||||
|         private enum AUTH_INFO_STATE { | ||||
|             PROTOCOL, | ||||
|             HOSTNAME, | ||||
|             PORT, | ||||
|             PASSWORD | ||||
|         }; | ||||
|  | ||||
|         private AUTH_INFO_STATE infoState; | ||||
|  | ||||
|         @Override | ||||
|         public void endElement(String uri, String localName, String qName) throws SAXException { | ||||
|  | ||||
|             if (localName.equals("authorize")) { | ||||
|  | ||||
|                 // Finalize mapping for this user | ||||
|                 authMapping.put( | ||||
|                     current.auth_username, | ||||
|                     current | ||||
|                 ); | ||||
|  | ||||
|             } | ||||
|  | ||||
|             infoState = null; | ||||
|  | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { | ||||
|  | ||||
|             if (localName.equals("authorize")) { | ||||
|  | ||||
|                 AuthInfo.Encoding encoding; | ||||
|                 String encodingString = attributes.getValue("encoding"); | ||||
|                 if (encodingString == null) | ||||
|                     encoding = AuthInfo.Encoding.PLAIN_TEXT; | ||||
|                 else if (encodingString.equals("plain")) | ||||
|                     encoding = AuthInfo.Encoding.PLAIN_TEXT; | ||||
|                 else if (encodingString.equals("md5")) | ||||
|                     encoding = AuthInfo.Encoding.MD5; | ||||
|                 else | ||||
|                     throw new SAXException("Invalid encoding type"); | ||||
|  | ||||
|  | ||||
|                 current = new AuthInfo( | ||||
|                     attributes.getValue("username"), | ||||
|                     attributes.getValue("password"), | ||||
|                     encoding | ||||
|                 ); | ||||
|  | ||||
|                 infoState = null; | ||||
|  | ||||
|             } | ||||
|  | ||||
|             else if (localName.equals("protocol")) | ||||
|                 infoState = AUTH_INFO_STATE.PROTOCOL; | ||||
|  | ||||
|             else if (localName.equals("hostname")) | ||||
|                 infoState = AUTH_INFO_STATE.HOSTNAME; | ||||
|  | ||||
|             else if (localName.equals("port")) | ||||
|                 infoState = AUTH_INFO_STATE.PORT; | ||||
|  | ||||
|             else if (localName.equals("password")) | ||||
|                 infoState = AUTH_INFO_STATE.PASSWORD; | ||||
|  | ||||
|             else | ||||
|                 infoState = null; | ||||
|  | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void characters(char[] ch, int start, int length) throws SAXException { | ||||
|  | ||||
|             String str = new String(ch, start, length); | ||||
|  | ||||
|             if (infoState == null) | ||||
|                 return; | ||||
|  | ||||
|             switch (infoState) { | ||||
|  | ||||
|                 case PROTOCOL: | ||||
|                     current.protocol = str; | ||||
|                     break; | ||||
|  | ||||
|                 case HOSTNAME: | ||||
|                     current.hostname = str; | ||||
|                     break; | ||||
|  | ||||
|                 case PORT: | ||||
|                     current.port = Integer.parseInt(str); | ||||
|                     break; | ||||
|  | ||||
|                 case PASSWORD: | ||||
|                     current.password = str; | ||||
|                     break; | ||||
|  | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,50 @@ | ||||
|  | ||||
| package net.sourceforge.guacamole.net.authentication.basic; | ||||
|  | ||||
| import javax.servlet.http.HttpSession; | ||||
| import net.sourceforge.guacamole.GuacamoleException; | ||||
| import net.sourceforge.guacamole.net.GuacamoleSession; | ||||
| import net.sourceforge.guacamole.net.authentication.GuacamoleSessionProvider; | ||||
|  | ||||
| /* | ||||
|  *  Guacamole - Clientless Remote Desktop | ||||
|  *  Copyright (C) 2010  Michael Jumper | ||||
|  * | ||||
|  *  This program is free software: you can redistribute it and/or modify | ||||
|  *  it under the terms of the GNU Affero General Public License as published by | ||||
|  *  the Free Software Foundation, either version 3 of the License, or | ||||
|  *  (at your option) any later version. | ||||
|  * | ||||
|  *  This program is distributed in the hope that it will be useful, | ||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *  GNU Affero General Public License for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU Affero General Public License | ||||
|  *  along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| public class BasicGuacamoleSessionProvider implements GuacamoleSessionProvider { | ||||
|  | ||||
|     public GuacamoleSession createSession(HttpSession session) throws GuacamoleException { | ||||
|  | ||||
|         // Retrieve authorized config data from session | ||||
|         BasicLogin.AuthorizedConfiguration config = (BasicLogin.AuthorizedConfiguration) | ||||
|                 session.getAttribute("BASIC-LOGIN-AUTH"); | ||||
|  | ||||
|         // If no data, not authorized | ||||
|         if (config == null) | ||||
|             throw new GuacamoleException("Unauthorized"); | ||||
|  | ||||
|         // Configure session from authorized config info | ||||
|         GuacamoleSession guacSession = new GuacamoleSession(session); | ||||
|         guacSession.setConnection(config.getProtocol(), config.getHostname(), config.getPort()); | ||||
|         if (config.getPassword() != null) | ||||
|             guacSession.setPassword(config.getPassword()); | ||||
|  | ||||
|         // Return authorized session | ||||
|         return guacSession; | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,161 @@ | ||||
|  | ||||
| package net.sourceforge.guacamole.net.authentication.basic; | ||||
|  | ||||
| /* | ||||
|  *  Guacamole - Clientless Remote Desktop | ||||
|  *  Copyright (C) 2010  Michael Jumper | ||||
|  * | ||||
|  *  This program is free software: you can redistribute it and/or modify | ||||
|  *  it under the terms of the GNU Affero General Public License as published by | ||||
|  *  the Free Software Foundation, either version 3 of the License, or | ||||
|  *  (at your option) any later version. | ||||
|  * | ||||
|  *  This program is distributed in the hope that it will be useful, | ||||
|  *  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  *  GNU Affero General Public License for more details. | ||||
|  * | ||||
|  *  You should have received a copy of the GNU Affero General Public License | ||||
|  *  along with this program.  If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| import java.io.IOException; | ||||
| import java.lang.reflect.InvocationTargetException; | ||||
| import javax.servlet.ServletException; | ||||
| import javax.servlet.http.HttpServlet; | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
| import javax.servlet.http.HttpServletResponse; | ||||
| import javax.servlet.http.HttpSession; | ||||
| import net.sourceforge.guacamole.GuacamoleException; | ||||
| import net.sourceforge.guacamole.net.Configuration; | ||||
|  | ||||
| public class BasicLogin extends HttpServlet { | ||||
|  | ||||
|     private Config config; | ||||
|  | ||||
|     @Override | ||||
|     public void init() throws ServletException { | ||||
|         try { | ||||
|             config = new Config(); | ||||
|         } | ||||
|         catch (GuacamoleException e) { | ||||
|             throw new ServletException(e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|  | ||||
|     private class Config extends Configuration { | ||||
|  | ||||
|         private AuthenticationProvider authProvider; | ||||
|  | ||||
|         public Config() throws GuacamoleException { | ||||
|  | ||||
|             // Get auth provider instance | ||||
|             try { | ||||
|                 String authProviderClassName = readParameter("auth-provider"); | ||||
|                 Object obj = Class.forName(authProviderClassName).getConstructor().newInstance(); | ||||
|                 if (!(obj instanceof AuthenticationProvider)) | ||||
|                     throw new GuacamoleException("Specified session provider class is not a GuacamoleSessionProvider"); | ||||
|  | ||||
|                 authProvider = (AuthenticationProvider) obj; | ||||
|             } | ||||
|             catch (ClassNotFoundException e) { | ||||
|                 throw new GuacamoleException("Session provider class not found", e); | ||||
|             } | ||||
|             catch (NoSuchMethodException e) { | ||||
|                 throw new GuacamoleException("Default constructor for session provider not present", e); | ||||
|             } | ||||
|             catch (SecurityException e) { | ||||
|                 throw new GuacamoleException("Creation of session provider disallowed; check your security settings", e); | ||||
|             } | ||||
|             catch (InstantiationException e) { | ||||
|                 throw new GuacamoleException("Unable to instantiate session provider", e); | ||||
|             } | ||||
|             catch (IllegalAccessException e) { | ||||
|                 throw new GuacamoleException("Unable to access default constructor of session provider", e); | ||||
|             } | ||||
|             catch (InvocationTargetException e) { | ||||
|                 throw new GuacamoleException("Internal error in constructor of session provider", e.getTargetException()); | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         public AuthenticationProvider getAuthenticationProvider() { | ||||
|             return authProvider; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public static interface AuthenticationProvider { | ||||
|         public AuthorizedConfiguration getAuthorizedConfiguration(String username, String password) throws GuacamoleException; | ||||
|     } | ||||
|  | ||||
|     // Added to session when session validated | ||||
|     public static class AuthorizedConfiguration { | ||||
|  | ||||
|         private String protocol; | ||||
|         private String hostname; | ||||
|         private int port; | ||||
|         private String password; | ||||
|  | ||||
|         public AuthorizedConfiguration(String protocol, String hostname, int port, String password) { | ||||
|             this.protocol = protocol; | ||||
|             this.hostname = hostname; | ||||
|             this.port = port; | ||||
|             this.password = password; | ||||
|         } | ||||
|  | ||||
|         public String getHostname() { | ||||
|             return hostname; | ||||
|         } | ||||
|  | ||||
|         public String getPassword() { | ||||
|             return password; | ||||
|         } | ||||
|  | ||||
|         public int getPort() { | ||||
|             return port; | ||||
|         } | ||||
|  | ||||
|         public String getProtocol() { | ||||
|             return protocol; | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { | ||||
|  | ||||
|         // Retrieve username and password from parms | ||||
|         String username = req.getParameter("username"); | ||||
|         String password = req.getParameter("password"); | ||||
|  | ||||
|         // Validate username and password | ||||
|         try { | ||||
|  | ||||
|             AuthorizedConfiguration info = config.getAuthenticationProvider().getAuthorizedConfiguration(username, password); | ||||
|             if (info != null) { | ||||
|  | ||||
|                 // Store authorized configuration | ||||
|                 HttpSession session = req.getSession(true); | ||||
|                 session.setAttribute( | ||||
|                     "BASIC-LOGIN-AUTH", | ||||
|                     info | ||||
|                 ); | ||||
|  | ||||
|                 // Success | ||||
|                 return; | ||||
|  | ||||
|             } | ||||
|  | ||||
|             // Report "forbidden" on any failure | ||||
|             resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Login invalid"); | ||||
|         } | ||||
|         catch (GuacamoleException e) { | ||||
|             throw new ServletException("Error validating credentials", e); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
		Reference in New Issue
	
	Block a user