1 #pragma once
2 
3 #include <boost/asio.hpp>
4 #include <boost/function.hpp>
5 #include <boost/thread.hpp>
6 #include "server.hpp"
7 #include "session_store.hpp"
8 
9 namespace http {
10 	namespace server {
11 		enum _eUserRights
12 		{
13 			URIGHTS_VIEWER=0,
14 			URIGHTS_SWITCHER,
15 			URIGHTS_ADMIN
16 		};
17 		enum _eAuthenticationMethod
18 		{
19 			AUTH_LOGIN=0,
20 			AUTH_BASIC,
21 		};
22 		enum _eWebCompressionMode
23 		{
24 			WWW_USE_GZIP=0,
25 			WWW_USE_STATIC_GZ_FILES,
26 			WWW_FORCE_NO_GZIP_SUPPORT
27 		};
28 		typedef struct _tWebUserPassword
29 		{
30 			unsigned long ID;
31 			std::string Username;
32 			std::string Password;
33 			_eUserRights userrights;
34 			int TotSensors;
35 			int ActiveTabs;
36 		} WebUserPassword;
37 
38 		typedef struct _tWebEmSession
39 		{
40 			std::string id;
41 			std::string remote_host;
42 			std::string auth_token;
43 			std::string username;
44 			int reply_status;
45 			time_t timeout;
46 			time_t expires;
47 			int rights;
48 			bool rememberme;
49 			bool isnew;
50 			bool forcelogin;
51 		} WebEmSession;
52 
53 		typedef struct _tIPNetwork
54 		{
55 			uint32_t network;
56 			uint32_t mask;
57 			std::string hostname;
58 		} IPNetwork;
59 
60 		// Parsed Authorization header
61 		struct ah {
62 			std::string method;
63 			std::string user;
64 			std::string response;
65 			std::string uri;
66 			std::string cnonce;
67 			std::string qop;
68 			std::string nc;
69 			std::string nonce;
70 			std::string ha1;
71 		};
72 
73 		/**
74 
75 		The link between the embedded web server and the application code
76 
77 
78 		* Copyright (c) 2008 by James Bremner
79 		* All rights reserved.
80 		*
81 		* Use license: Modified from standard BSD license.
82 		*
83 		* Redistribution and use in source and binary forms are permitted
84 		* provided that the above copyright notice and this paragraph are
85 		* duplicated in all such forms and that any documentation, advertising
86 		* materials, Web server pages, and other materials related to such
87 		* distribution and use acknowledge that the software was developed
88 		* by James Bremner. The name "James Bremner" may not be used to
89 		* endorse or promote products derived from this software without
90 		* specific prior written permission.
91 		*
92 		* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
93 		* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
94 		* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
95 
96 
97 
98 		*/
99 		class cWebem;
100 		typedef boost::function< void( std::string & content_part ) > webem_include_function;
101 		typedef boost::function< void( std::wstring & content_part_w ) > webem_include_function_w;
102 		typedef boost::function< void( WebEmSession & session, const request& req, std::string & redirecturi ) > webem_action_function;
103 		typedef boost::function< void( WebEmSession & session, const request & req, reply & rep ) > webem_page_function;
104 
105 
106 		/**
107 
108 		The webem request handler.
109 
110 		A specialization of the boost::asio request handler
111 
112 		Application code should not use this class.
113 
114 		*/
115 		class cWebemRequestHandler : public request_handler
116 		{
117 		public:
118 			/// Construct with a directory containing files to be served.
cWebemRequestHandler(const std::string & doc_root,cWebem * webem)119 			cWebemRequestHandler( const std::string& doc_root, cWebem* webem ) :
120 				request_handler( doc_root, webem )
121 				{}
122 
123 			/// Handle a request and produce a reply.
124 			virtual void handle_request(const request& req, reply& rep) override;
125 		private:
126 			char *strftime_t(const char *format, const time_t rawtime);
127 			bool CompressWebOutput(const request& req, reply& rep);
128 			/// Websocket methods
129 			bool is_upgrade_request(WebEmSession & session, const request& req, reply& rep);
130 			std::string compute_accept_header(const std::string &websocket_key);
131 			bool CheckAuthentication(WebEmSession & session, const request& req, reply& rep);
132 			void send_authorization_request(reply& rep);
133 			void send_remove_cookie(reply& rep);
134 			std::string generateSessionID();
135 			void send_cookie(reply& rep, const WebEmSession & session);
136 			bool AreWeInLocalNetwork(const std::string &sHost, const request& req);
137 			int authorize(WebEmSession & session, const request& req, reply& rep);
138 			void Logout();
139 			int parse_auth_header(const request& req, struct ah *ah);
140 			std::string generateAuthToken(const WebEmSession & session, const request & req);
141 			bool checkAuthToken(WebEmSession & session);
142 			void removeAuthToken(const std::string & sessionId);
143 	};
144 		// forward declaration for friend declaration
145 		class CProxyClient;
146 		/**
147 
148 		The webem embedded web server.
149 
150 		*/
151 		class cWebem
152 		{
153 		friend class CProxyClient;
154 		public:
155 			cWebem(
156 				const server_settings & settings,
157 				const std::string& doc_root);
158 			~cWebem();
159 			void Run();
160 			void Stop();
161 
162 			void RegisterIncludeCode(
163 				const char* idname,
164 				webem_include_function fun );
165 
166 			void RegisterIncludeCodeW(
167 				const char* idname,
168 				webem_include_function_w fun );
169 
170 			void RegisterPageCode(
171 				const char* pageurl,
172 				webem_page_function fun,
173 				bool bypassAuthentication = false
174 			);
175 			void RegisterPageCodeW(
176 				const char* pageurl,
177 				webem_page_function fun,
178 				bool bypassAuthentication = false
179 			);
180 
181 			bool Include( std::string& reply );
182 
183 			void RegisterActionCode(
184 				const char* idname,
185 				webem_action_function fun );
186 
187 			void RegisterWhitelistURLString(const char* idname);
188 			void RegisterWhitelistCommandsString(const char* idname);
189 
190 			bool IsAction(const request& req);
191 			bool CheckForAction(WebEmSession & session, request& req);
192 
193 			bool IsPageOverride(const request& req, reply& rep);
194 			bool CheckForPageOverride(WebEmSession & session, request& req, reply& rep);
195 
196 			void SetAuthenticationMethod(const _eAuthenticationMethod amethod);
197 			void SetWebTheme(const std::string &themename);
198 			void SetWebRoot(const std::string &webRoot);
199 			void AddUserPassword(const unsigned long ID, const std::string &username, const std::string &password, const _eUserRights userrights, const int activetabs);
200 			std::string ExtractRequestPath(const std::string& original_request_path);
201 			bool IsBadRequestPath(const std::string& original_request_path);
202 
203 			void ClearUserPasswords();
204 			std::vector<_tWebUserPassword> m_userpasswords;
205 			void AddLocalNetworks(std::string network);
206 			void ClearLocalNetworks();
207 			std::vector<_tIPNetwork> m_localnetworks;
208 			void SetDigistRealm(const std::string &realm);
209 			std::string m_DigistRealm;
210 			void SetZipPassword(const std::string &password);
211 
212 			//IPs that are allowed to pass proxy headers
213 			std::vector < std::string > myRemoteProxyIPs;
214 			void AddRemoteProxyIPs(const std::string &ipaddr);
215 			void ClearRemoteProxyIPs();
216 
217 			// Session store manager
218 			void SetSessionStore(session_store_impl_ptr sessionStore);
219 			session_store_impl_ptr GetSessionStore();
220 
221 			std::string m_zippassword;
222 			const std::string GetPort();
223 			const std::string GetWebRoot();
224 			WebEmSession * GetSession(const std::string & ssid);
225 			void AddSession(const WebEmSession & session);
226 			void RemoveSession(const WebEmSession & session);
227 			void RemoveSession(const std::string & ssid);
228 			int CountSessions();
229 			_eAuthenticationMethod m_authmethod;
230 			//Whitelist url strings that bypass authentication checks (not used by basic-auth authentication)
231 			std::vector < std::string > myWhitelistURLs;
232 			std::vector < std::string > myWhitelistCommands;
233 			std::map<std::string, WebEmSession> m_sessions;
234 			server_settings m_settings;
235 			// actual theme selected
236 			std::string m_actTheme;
237 
238 			void SetWebCompressionMode(const _eWebCompressionMode gzmode);
239 			_eWebCompressionMode m_gzipmode;
240 		private:
241 			/// store map between include codes and application functions
242 			std::map < std::string, webem_include_function > myIncludes;
243 			/// store map between include codes and application functions returning UTF-16 strings
244 			std::map < std::string, webem_include_function_w > myIncludes_w;
245 			/// store map between action codes and application functions
246 			std::map < std::string, webem_action_function > myActions;
247 			/// store name walue pairs for form submit action
248 			std::map < std::string, webem_page_function > myPages;
249 			/// store map between pages and application functions
250 			std::map < std::string, webem_page_function > myPages_w;
251 			void CleanSessions();
252 			session_store_impl_ptr mySessionStore; /// session store
253 			/// request handler specialized to handle webem requests
254 			/// Rene: Beware: myRequestHandler should be declared BEFORE myServer
255 			cWebemRequestHandler myRequestHandler;
256 			/// boost::asio web server (RK: plain or secure)
257 			std::shared_ptr<server_base> myServer;
258 			// root of url for reverse proxy servers
259 			std::string m_webRoot;
260 			/// sessions management
261 			std::mutex m_sessionsMutex;
262 			boost::asio::io_service m_io_service;
263 			boost::asio::deadline_timer m_session_clean_timer;
264 			std::shared_ptr<std::thread> m_io_service_thread;
265 		};
266 
267 	}
268 }
269