Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

keepass.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2020 The Dash Core developers
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <keepass.h>
6 
7 #include <wallet/crypter.h>
8 #include <clientversion.h>
9 #include <protocol.h>
10 #include <random.h>
11 #include <rpc/protocol.h>
12 
13 // Necessary to prevent compile errors due to forward declaration of
14 //CScript in serialize.h (included from crypter.h)
15 #include <script/script.h>
16 #include <script/standard.h>
17 
18 #include <util.h>
19 #include <utilstrencodings.h>
20 
21 #include <event2/event.h>
22 #include <event2/http.h>
23 #include <event2/buffer.h>
24 #include <event2/keyvalq_struct.h>
25 
26 #include <openssl/bio.h>
27 #include <openssl/evp.h>
28 #include <openssl/buffer.h>
29 #include <support/cleanse.h> // for OPENSSL_cleanse()
30 
31 const char* CKeePassIntegrator::KEEPASS_HTTP_HOST = "localhost";
32 
34 
35 // Base64 decoding with secure memory allocation
37 {
38  SecureString output;
39 
40  // Init openssl BIO with base64 filter and memory input
41  BIO *b64, *mem;
42  b64 = BIO_new(BIO_f_base64());
43  BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); //Do not use newlines to flush buffer
44  mem = BIO_new_mem_buf((void *) sInput.data(), sInput.size());
45  BIO_push(b64, mem);
46 
47  // Prepare buffer to receive decoded data
48  if(sInput.size() % 4 != 0) {
49  throw std::runtime_error("Input length should be a multiple of 4");
50  }
51  size_t nMaxLen = sInput.size() / 4 * 3; // upper bound, guaranteed divisible by 4
52  output.resize(nMaxLen);
53 
54  // Decode the string
55  size_t nLen;
56  nLen = BIO_read(b64, (void *) output.data(), sInput.size());
57  output.resize(nLen);
58 
59  // Free memory
60  BIO_free_all(b64);
61  return output;
62 }
63 
64 // Base64 encoding with secure memory allocation
66 {
67  // Init openssl BIO with base64 filter and memory output
68  BIO *b64, *mem;
69  b64 = BIO_new(BIO_f_base64());
70  BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); // No newlines in output
71  mem = BIO_new(BIO_s_mem());
72  BIO_push(b64, mem);
73 
74  // Decode the string
75  BIO_write(b64, sInput.data(), sInput.size());
76  (void) BIO_flush(b64);
77 
78  // Create output variable from buffer mem ptr
79  BUF_MEM *bptr;
80  BIO_get_mem_ptr(b64, &bptr);
81  SecureString output(bptr->data, bptr->length);
82 
83  // Cleanse secure data buffer from memory
84  memory_cleanse((void *) bptr->data, bptr->length);
85 
86  // Free memory
87  BIO_free_all(b64);
88  return output;
89 }
90 
92  :sKeyBase64(" "), sKey(" "), sUrl(" ") // Prevent LockedPageManagerBase complaints
93 {
94  sKeyBase64.clear(); // Prevent LockedPageManagerBase complaints
95  sKey.clear(); // Prevent LockedPageManagerBase complaints
96  sUrl.clear(); // Prevent LockedPageManagerBase complaints
97  bIsActive = false;
99 }
100 
101 // Initialze from application context
103 {
104  bIsActive = gArgs.GetBoolArg("-keepass", false);
105  nPort = gArgs.GetArg("-keepassport", DEFAULT_KEEPASS_HTTP_PORT);
106  sKeyBase64 = SecureString(gArgs.GetArg("-keepasskey", "").c_str());
107  strKeePassId = gArgs.GetArg("-keepassid", "");
108  strKeePassEntryName = gArgs.GetArg("-keepassname", "");
109  // Convert key if available
110  if(sKeyBase64.size() > 0)
111  {
113  }
114  // Construct url if available
115  if(strKeePassEntryName.size() > 0)
116  {
117  sUrl = SecureString("http://");
119  sUrl += SecureString("/");
120  }
121 }
122 
123 void CKeePassIntegrator::CKeePassRequest::addStrParameter(const std::string& strName, const std::string& strValue)
124 {
125  requestObj.push_back(Pair(strName, strValue));
126 }
127 
128 void CKeePassIntegrator::CKeePassRequest::addStrParameter(const std::string& strName, const SecureString& sValue)
129 {
130  std::string sCipherValue;
131 
132  if(!EncryptAES256(sKey, sValue, strIV, sCipherValue))
133  {
134  throw std::runtime_error("Unable to encrypt Verifier");
135  }
136 
137  addStrParameter(strName, EncodeBase64(sCipherValue));
138 }
139 
141 {
142  return requestObj.write();
143 }
144 
146 {
148  strIV = std::string(sIVSecure.data(), sIVSecure.size());
149  // Generate Nonce, Verifier and RequestType
150  SecureString sNonceBase64Secure = EncodeBase64Secure(sIVSecure);
151  addStrParameter("Nonce", std::string(sNonceBase64Secure.data(), sNonceBase64Secure.size())); // Plain
152  addStrParameter("Verifier", sNonceBase64Secure); // Encoded
153  addStrParameter("RequestType", strType);
154 }
155 
156 void CKeePassIntegrator::CKeePassResponse::parseResponse(const std::string& strResponse)
157 {
158  UniValue responseValue;
159  if(!responseValue.read(strResponse))
160  {
161  throw std::runtime_error("Unable to parse KeePassHttp response");
162  }
163 
164  responseObj = responseValue;
165 
166  // retrieve main values
167  bSuccess = responseObj["Success"].get_bool();
168  strType = getStr("RequestType");
169  strIV = DecodeBase64(getStr("Nonce"));
170 }
171 
172 std::string CKeePassIntegrator::CKeePassResponse::getStr(const std::string& strName)
173 {
174  return responseObj[strName].get_str();
175 }
176 
178 {
179  std::string strValueBase64Encrypted(responseObj[strName].get_str());
180  SecureString sValue;
181  try
182  {
183  sValue = decrypt(strValueBase64Encrypted);
184  }
185  catch (std::exception &e)
186  {
187  std::string strError = "Exception occured while decrypting ";
188  strError += strName + ": " + e.what();
189  throw std::runtime_error(strError);
190  }
191  return sValue;
192 }
193 
194 SecureString CKeePassIntegrator::CKeePassResponse::decrypt(const std::string& strValueBase64Encrypted)
195 {
196  std::string strValueEncrypted = DecodeBase64(strValueBase64Encrypted);
197  SecureString sValue;
198  if(!DecryptAES256(sKey, strValueEncrypted, strIV, sValue))
199  {
200  throw std::runtime_error("Unable to decrypt value.");
201  }
202  return sValue;
203 }
204 
205 std::vector<CKeePassIntegrator::CKeePassEntry> CKeePassIntegrator::CKeePassResponse::getEntries()
206 {
207 
208  std::vector<CKeePassEntry> vEntries;
209 
210  UniValue aEntries = responseObj["Entries"].get_array();
211  for(size_t i = 0; i < aEntries.size(); i++)
212  {
213  SecureString sEntryUuid(decrypt(aEntries[i]["Uuid"].get_str().c_str()));
214  SecureString sEntryName(decrypt(aEntries[i]["Name"].get_str().c_str()));
215  SecureString sEntryLogin(decrypt(aEntries[i]["Login"].get_str().c_str()));
216  SecureString sEntryPassword(decrypt(aEntries[i]["Password"].get_str().c_str()));
217  CKeePassEntry entry(sEntryUuid, sEntryName, sEntryLogin, sEntryPassword);
218  vEntries.push_back(entry);
219  }
220 
221  return vEntries;
222 
223 }
224 
226 {
227  // Generates random key
229  sKey.resize(nSize);
230 
231  GetStrongRandBytes((unsigned char *) sKey.data(), nSize);
232 
233  return sKey;
234 }
235 
236 // Construct POST body for RPC JSON call
237 std::string CKeePassIntegrator::constructHTTPPost(const std::string& strMsg, const std::map<std::string,std::string>& mapRequestHeaders)
238 {
239  std::ostringstream streamOut;
240  streamOut << "POST / HTTP/1.1\r\n"
241  << "User-Agent: dash-json-rpc/" << FormatFullVersion() << "\r\n"
242  << "Host: localhost\r\n"
243  << "Content-Type: application/json\r\n"
244  << "Content-Length: " << strMsg.size() << "\r\n"
245  << "Connection: close\r\n"
246  << "Accept: application/json\r\n";
247  for (const auto& item : mapRequestHeaders)
248  streamOut << item.first << ": " << item.second << "\r\n";
249  streamOut << "\r\n" << strMsg;
250 
251  return streamOut.str();
252 }
253 
255 struct HTTPReply
256 {
257  int nStatus;
258  std::string strBody;
259 };
260 
261 static void http_request_done(struct evhttp_request *req, void *ctx)
262 {
263  HTTPReply *reply = static_cast<HTTPReply*>(ctx);
264 
265  if (req == nullptr) {
266  /* If req is nullptr, it means an error occurred while connecting, but
267  * I'm not sure how to find out which one. We also don't really care.
268  */
269  reply->nStatus = 0;
270  return;
271  }
272 
273  reply->nStatus = evhttp_request_get_response_code(req);
274 
275  struct evbuffer *buf = evhttp_request_get_input_buffer(req);
276  if (buf)
277  {
278  size_t size = evbuffer_get_length(buf);
279  const char *data = (const char*)evbuffer_pullup(buf, size);
280  if (data)
281  reply->strBody = std::string(data, size);
282  evbuffer_drain(buf, size);
283  }
284 }
285 
286 // Send RPC message to KeePassHttp
287 void CKeePassIntegrator::doHTTPPost(const std::string& sRequest, int& nStatusRet, std::string& strResponseRet)
288 {
289  // Create event base
290  struct event_base *base = event_base_new(); // TODO RAII
291  if (!base)
292  throw std::runtime_error("cannot create event_base");
293 
294  // Synchronously look up hostname
295  struct evhttp_connection *evcon = evhttp_connection_base_new(base, nullptr, KEEPASS_HTTP_HOST, DEFAULT_KEEPASS_HTTP_PORT); // TODO RAII
296  if (evcon == nullptr)
297  throw std::runtime_error("create connection failed");
298  evhttp_connection_set_timeout(evcon, KEEPASS_HTTP_CONNECT_TIMEOUT);
299 
300  HTTPReply response;
301  struct evhttp_request *req = evhttp_request_new(http_request_done, (void*)&response); // TODO RAII
302  if (req == nullptr)
303  throw std::runtime_error("create http request failed");
304 
305  struct evkeyvalq *output_headers = evhttp_request_get_output_headers(req);
306  assert(output_headers);
307  evhttp_add_header(output_headers, "User-Agent", ("dash-json-rpc/" + FormatFullVersion()).c_str());
308  evhttp_add_header(output_headers, "Host", KEEPASS_HTTP_HOST);
309  evhttp_add_header(output_headers, "Accept", "application/json");
310  evhttp_add_header(output_headers, "Content-Type", "application/json");
311  evhttp_add_header(output_headers, "Connection", "close");
312 
313  LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::doHTTPPost -- send POST data\n");
314 
315  struct evbuffer * output_buffer = evhttp_request_get_output_buffer(req);
316  assert(output_buffer);
317  evbuffer_add(output_buffer, sRequest.data(), sRequest.size());
318 
319  int r = evhttp_make_request(evcon, req, EVHTTP_REQ_POST, "/");
320  if (r != 0) {
321  evhttp_connection_free(evcon);
322  event_base_free(base);
323  throw std::runtime_error("send http request failed");
324  }
325 
326  event_base_dispatch(base);
327  evhttp_connection_free(evcon);
328  event_base_free(base);
329 
330  nStatusRet = response.nStatus;
331  if (response.nStatus == 0)
332  throw std::runtime_error("couldn't connect to server");
333  else if (response.nStatus >= 400 && response.nStatus != HTTP_BAD_REQUEST && response.nStatus != HTTP_NOT_FOUND && response.nStatus != HTTP_INTERNAL_SERVER_ERROR)
334  throw std::runtime_error(strprintf("server returned HTTP error %d", response.nStatus));
335  else if (response.strBody.empty())
336  throw std::runtime_error("no response from server");
337 
338  // Parse reply
339  UniValue valReply(UniValue::VSTR);
340  if (!valReply.read(response.strBody))
341  throw std::runtime_error("couldn't parse reply from server");
342  const UniValue& reply = valReply.get_obj();
343  if (reply.empty())
344  throw std::runtime_error("expected reply to have result, error and id properties");
345 
346  strResponseRet = valReply.get_str();
347 }
348 
349 void CKeePassIntegrator::rpcTestAssociation(bool bTriggerUnlock)
350 {
351  CKeePassRequest request(sKey, "test-associate");
352  request.addStrParameter("TriggerUnlock", std::string(bTriggerUnlock ? "true" : "false"));
353 
354  int nStatus;
355  std::string strResponse;
356 
357  doHTTPPost(request.getJson(), nStatus, strResponse);
358 
359  LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::rpcTestAssociation -- send result: status: %d response: %s\n", nStatus, strResponse);
360 }
361 
362 std::vector<CKeePassIntegrator::CKeePassEntry> CKeePassIntegrator::rpcGetLogins()
363 {
364 
365  // Convert key format
367 
368  CKeePassRequest request(sKey, "get-logins");
369  request.addStrParameter("addStrParameter", std::string("true"));
370  request.addStrParameter("TriggerUnlock", std::string("true"));
371  request.addStrParameter("Id", strKeePassId);
372  request.addStrParameter("Url", sUrl);
373 
374  int nStatus;
375  std::string strResponse;
376 
377  doHTTPPost(request.getJson(), nStatus, strResponse);
378 
379  LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::rpcGetLogins -- send result: status: %d\n", nStatus);
380 
381  if(nStatus != 200)
382  {
383  std::string strError = "Error returned by KeePassHttp: HTTP code ";
384  strError += itostr(nStatus);
385  strError += " - Response: ";
386  strError += " response: [";
387  strError += strResponse;
388  strError += "]";
389  throw std::runtime_error(strError);
390  }
391 
392  // Parse the response
393  CKeePassResponse response(sKey, strResponse);
394 
395  if(!response.getSuccess())
396  {
397  std::string strError = "KeePassHttp returned failure status";
398  throw std::runtime_error(strError);
399  }
400 
401  return response.getEntries();
402 }
403 
404 void CKeePassIntegrator::rpcSetLogin(const SecureString& sWalletPass, const SecureString& sEntryId)
405 {
406 
407  // Convert key format
409 
410  CKeePassRequest request(sKey, "set-login");
411  request.addStrParameter("Id", strKeePassId);
412  request.addStrParameter("Url", sUrl);
413 
414  LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::rpcSetLogin -- send Url: %s\n", sUrl);
415 
416  //request.addStrParameter("SubmitUrl", sSubmitUrl); // Is used to construct the entry title
417  request.addStrParameter("Login", SecureString("dash"));
418  request.addStrParameter("Password", sWalletPass);
419  if(sEntryId.size() != 0)
420  {
421  request.addStrParameter("Uuid", sEntryId); // Update existing
422  }
423 
424  int nStatus;
425  std::string strResponse;
426 
427  doHTTPPost(request.getJson(), nStatus, strResponse);
428 
429 
430  LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::rpcSetLogin -- send result: status: %d response: %s\n", nStatus, strResponse);
431 
432  if(nStatus != 200)
433  {
434  std::string strError = "Error returned: HTTP code ";
435  strError += itostr(nStatus);
436  strError += " - Response: ";
437  strError += " response: [";
438  strError += strResponse;
439  strError += "]";
440  throw std::runtime_error(strError);
441  }
442 
443  // Parse the response
444  CKeePassResponse response(sKey, strResponse);
445 
446  if(!response.getSuccess())
447  {
448  throw std::runtime_error("KeePassHttp returned failure status");
449  }
450 }
451 
452 
454 {
457  return sKeyBase64;
458 }
459 
460 void CKeePassIntegrator::rpcAssociate(std::string& strIdRet, SecureString& sKeyBase64Ret)
461 {
463  CKeePassRequest request(sKey, "associate");
464 
465  sKeyBase64Ret = EncodeBase64Secure(sKey);
466  request.addStrParameter("Key", std::string(sKeyBase64Ret.data(), sKeyBase64Ret.size()));
467 
468  int nStatus;
469  std::string strResponse;
470 
471  doHTTPPost(request.getJson(), nStatus, strResponse);
472 
473  LogPrint(BCLog::KEEPASS, "CKeePassIntegrator::rpcAssociate -- send result: status: %d response: %s\n", nStatus, strResponse);
474 
475  if(nStatus != 200)
476  {
477  std::string strError = "Error returned: HTTP code ";
478  strError += itostr(nStatus);
479  strError += " - Response: ";
480  strError += " response: [";
481  strError += strResponse;
482  strError += "]";
483  throw std::runtime_error(strError);
484  }
485 
486  // Parse the response
487  CKeePassResponse response(sKey, strResponse);
488 
489  if(!response.getSuccess())
490  {
491  throw std::runtime_error("KeePassHttp returned failure status");
492  }
493 
494  // If we got here, we were successful. Return the information
495  strIdRet = response.getStr("Id");
496 }
497 
498 // Retrieve wallet passphrase from KeePass
500 {
501 
502  // Check we have all required information
503  if(sKey.size() == 0)
504  {
505  throw std::runtime_error("keepasskey parameter is not defined. Please specify the configuration parameter.");
506  }
507  if(strKeePassId.size() == 0)
508  {
509  throw std::runtime_error("keepassid parameter is not defined. Please specify the configuration parameter.");
510  }
511  if(strKeePassEntryName == "")
512  {
513  throw std::runtime_error("keepassname parameter is not defined. Please specify the configuration parameter.");
514  }
515 
516  // Retrieve matching logins from KeePass
517  std::vector<CKeePassIntegrator::CKeePassEntry> vecEntries = rpcGetLogins();
518 
519  // Only accept one unique match
520  if(vecEntries.size() == 0)
521  {
522  throw std::runtime_error("KeePassHttp returned 0 matches, please verify the keepassurl setting.");
523  }
524  if(vecEntries.size() > 1)
525  {
526  throw std::runtime_error("KeePassHttp returned multiple matches, bailing out.");
527  }
528 
529  return vecEntries[0].getPassword();
530 }
531 
532 // Update wallet passphrase in keepass
534 {
535  // Check we have all required information
536  if(sKey.size() == 0)
537  {
538  throw std::runtime_error("keepasskey parameter is not defined. Please specify the configuration parameter.");
539  }
540  if(strKeePassId.size() == 0)
541  {
542  throw std::runtime_error("keepassid parameter is not defined. Please specify the configuration parameter.");
543  }
544  if(strKeePassEntryName == "")
545  {
546  throw std::runtime_error("keepassname parameter is not defined. Please specify the configuration parameter.");
547  }
548 
549  SecureString sEntryId("");
550 
551  std::string strError;
552 
553  // Lookup existing entry
554  std::vector<CKeePassIntegrator::CKeePassEntry> vecEntries = rpcGetLogins();
555 
556  if(vecEntries.size() > 1)
557  {
558  throw std::runtime_error("KeePassHttp returned multiple matches, bailing out.");
559  }
560 
561  if(vecEntries.size() == 1)
562  {
563  sEntryId = vecEntries[0].getUuid();
564  }
565 
566  // Update wallet passphrase in KeePass
567  rpcSetLogin(sWalletPassphrase, sEntryId);
568 }
SecureString sKey
Definition: keepass.h:28
std::string strKeePassId
Definition: keepass.h:31
void parseResponse(const std::string &strResponse)
Definition: keepass.cpp:156
void addStrParameter(const std::string &strName, const std::string &strValue)
Definition: keepass.cpp:123
SecureString sKeyBase64
Definition: keepass.h:27
std::vector< unsigned char > DecodeBase64(const char *p, bool *pfInvalid)
void updatePassphrase(const SecureString &sWalletPassphrase)
Definition: keepass.cpp:533
bool get_bool() const
bool EncryptAES256(const SecureString &sKey, const SecureString &sPlaintext, const std::string &sIV, std::string &sCiphertext)
Definition: crypter.cpp:123
static const unsigned int DEFAULT_KEEPASS_HTTP_PORT
Definition: keepass.h:14
SecureString EncodeBase64Secure(const SecureString &sInput)
Definition: keepass.cpp:65
bool read(const char *raw, size_t len)
#define strprintf
Definition: tinyformat.h:1066
std::string strBody
Definition: keepass.cpp:258
std::basic_string< char, std::char_traits< char >, secure_allocator< char > > SecureString
Definition: secure.h:57
void GetStrongRandBytes(unsigned char *out, int num)
Function to gather random data from multiple sources, failing whenever any of those source fail to pr...
Definition: random.cpp:317
const std::string & get_str() const
const UniValue & get_array() const
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: util.cpp:824
std::vector< CKeePassEntry > getEntries()
Definition: keepass.cpp:205
bool DecryptAES256(const SecureString &sKey, const std::string &sCiphertext, const std::string &sIV, SecureString &sPlaintext)
Definition: crypter.cpp:155
void rpcAssociate(std::string &strIdRet, SecureString &sKeyBase64Ret)
Definition: keepass.cpp:460
static SecureString generateKeePassKey()
Definition: keepass.cpp:453
static const int KEEPASS_CRYPTO_BLOCK_SIZE
Definition: keepass.h:21
SecureString DecodeBase64Secure(const SecureString &sInput)
Definition: keepass.cpp:36
void memory_cleanse(void *ptr, size_t len)
Definition: cleanse.cpp:31
bool push_back(const UniValue &val)
Definition: univalue.cpp:110
static secp256k1_context * ctx
Definition: tests.c:46
static void http_request_done(struct evhttp_request *req, void *ctx)
Definition: keepass.cpp:261
unsigned int nPort
Definition: keepass.h:26
Definition: keepass.h:57
bool empty() const
Definition: univalue.h:67
static const int KEEPASS_CRYPTO_KEY_SIZE
Definition: keepass.h:20
std::string strKeePassEntryName
Definition: keepass.h:32
static std::pair< std::string, UniValue > Pair(const char *cKey, const char *cVal)
Definition: univalue.h:185
std::string FormatFullVersion()
void doHTTPPost(const std::string &strRequest, int &nStatusRet, std::string &strResponseRet)
Definition: keepass.cpp:287
#define LogPrint(category,...)
Definition: util.h:214
int nStatus
Definition: keepass.cpp:257
ArgsManager gArgs
Definition: util.cpp:108
static const int KEEPASS_HTTP_CONNECT_TIMEOUT
Definition: keepass.h:22
CKeePassIntegrator keePassInt
Definition: keepass.cpp:33
SecureString getSecureStr(const std::string &strName)
Definition: keepass.cpp:177
const UniValue & get_obj() const
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: util.cpp:808
static SecureString generateRandomKey(size_t nSize)
Definition: keepass.cpp:225
SecureString decrypt(const std::string &strValue)
Definition: keepass.cpp:194
SecureString retrievePassphrase()
Definition: keepass.cpp:499
static const char * KEEPASS_HTTP_HOST
Definition: keepass.h:23
size_t size() const
Definition: univalue.h:69
void rpcTestAssociation(bool bTriggerUnlock)
Definition: keepass.cpp:349
std::vector< CKeePassEntry > rpcGetLogins()
Definition: keepass.cpp:362
void rpcSetLogin(const SecureString &sWalletPass, const SecureString &sEntryId)
Definition: keepass.cpp:404
static std::string constructHTTPPost(const std::string &strMsg, const std::map< std::string, std::string > &mapRequestHeaders)
Definition: keepass.cpp:237
std::string itostr(int n)
Reply structure for request_done to fill in.
Definition: dash-cli.cpp:145
SecureString sUrl
Definition: keepass.h:29
std::string EncodeBase64(const unsigned char *pch, size_t len)
std::string getStr(const std::string &strName)
Definition: keepass.cpp:172
Released under the MIT license