1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2017 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2018-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "nel/gui/http_hsts.h"
24 using namespace NLMISC
;
31 CStrictTransportSecurity
* CStrictTransportSecurity::instance
= NULL
;
32 CStrictTransportSecurity
* CStrictTransportSecurity::getInstance()
36 instance
= new CStrictTransportSecurity();
41 void CStrictTransportSecurity::release()
47 CStrictTransportSecurity::~CStrictTransportSecurity()
52 // ************************************************************************
53 bool CStrictTransportSecurity::isSecureHost(const std::string
&domain
) const
56 if (get(domain
, hsts
))
61 return (hsts
.Expires
> currentTime
);
67 // ************************************************************************
68 void CStrictTransportSecurity::erase(const std::string
&domain
)
70 if (_Domains
.count(domain
) > 0)
72 _Domains
.erase(domain
);
76 void CStrictTransportSecurity::set(const std::string
&domain
, uint64 expires
, bool includeSubDomains
)
84 _Domains
[domain
].Expires
= expires
;
85 _Domains
[domain
].IncludeSubDomains
= includeSubDomains
;
88 bool CStrictTransportSecurity::get(const std::string
&domain
, SHSTSObject
&hsts
) const
90 if (domain
.empty() || _Domains
.empty())
93 THSTSObjectMap::const_iterator itHsts
;
95 itHsts
= _Domains
.find(domain
);
96 if (itHsts
!= _Domains
.end())
98 hsts
= itHsts
->second
;
102 size_t firstOf
= domain
.find_first_of(".");
103 size_t lastOf
= domain
.find_last_of(".");
104 while(firstOf
!= lastOf
)
107 tmp
= domain
.substr(firstOf
+1);
108 itHsts
= _Domains
.find(tmp
);
109 if (itHsts
!= _Domains
.end())
111 if (itHsts
->second
.IncludeSubDomains
)
113 hsts
= itHsts
->second
;
120 firstOf
= domain
.find_first_of(".", firstOf
+ 1);
126 void CStrictTransportSecurity::init(const std::string
&fname
)
131 if (_Filename
.empty() || !CFile::fileExists(_Filename
))
137 if (!in
.open(_Filename
))
139 nlwarning("Unable to open %s for reading", _Filename
.c_str());
146 void CStrictTransportSecurity::save()
148 if (_Filename
.empty())
151 if (_Domains
.empty())
153 CFile::deleteFile(_Filename
);
158 if (!out
.open(_Filename
))
160 nlwarning("Unable to open %s for writing", _Filename
.c_str());
168 void CStrictTransportSecurity::serial(NLMISC::IStream
& f
)
174 f
.serialCheck(NELID("STSH"));
180 for(uint32 k
= 0; k
< nbItems
; ++k
)
184 f
.serial(_Domains
[domain
].Expires
);
185 f
.serial(_Domains
[domain
].IncludeSubDomains
);
190 uint32 nbItems
= _Domains
.size();
192 for (THSTSObjectMap::iterator it
= _Domains
.begin(); it
!= _Domains
.end(); ++it
)
194 std::string
domain(it
->first
);
196 f
.serial(_Domains
[domain
].Expires
);
197 f
.serial(_Domains
[domain
].IncludeSubDomains
);
204 nlwarning("Invalid HTST file format (%s)", _Filename
.c_str());
208 // ***************************************************************************
209 void CStrictTransportSecurity::setFromHeader(const std::string
&domain
, const std::string
&header
)
211 // max-age=<seconds>; includeSubdomains; preload;
212 std::vector
<std::string
> elements
;
213 NLMISC::splitString(toLowerAscii(header
), ";", elements
);
214 if (elements
.empty()) return;
220 bool includeSubDomains
= false;
222 for(uint i
=0; i
< elements
.size(); ++i
)
224 std::string
str(trim(elements
[i
]));
225 if (str
.substr(0, 8) == "max-age=")
228 if (fromString(str
.substr(8), ttl
))
232 expire
= currentTime
+ ttl
;
236 else if (str
== "includesubdomains")
238 includeSubDomains
= true;
248 set(domain
, expire
, includeSubDomains
);