CernVM-FS  2.13.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
session_token.cc
Go to the documentation of this file.
1 
7 #include "session_token.h"
8 
9 #include <limits>
10 
11 #include "crypto/encrypt.h"
12 #include "json.h"
13 #include "json_document.h"
14 #include "util/logging.h"
15 #include "util/platform.h"
16 #include "util/pointer.h"
17 #include "util/string.h"
18 
19 namespace receiver {
20 
30 bool GenerateSessionToken(const std::string &key_id, const std::string &path,
31  uint64_t max_lease_time, std::string *session_token,
32  std::string *public_token_id,
33  std::string *token_secret) {
34  if (session_token == NULL || public_token_id == NULL
35  || token_secret == NULL) {
36  return false;
37  }
38 
39  if (key_id.empty() && path.empty()) {
40  return false;
41  }
42 
44  if (!secret.IsValid()) {
45  return false;
46  }
47 
49  if (!cipher.IsValid()) {
50  return false;
51  }
52 
53  *public_token_id = key_id + path;
54  *token_secret = secret->ToBase64();
55 
56  const uint64_t current_time = platform_monotonic_time();
57  if (std::numeric_limits<uint64_t>::max() - max_lease_time < current_time) {
58  return false;
59  }
60 
61  const std::string expiry(StringifyUint(current_time + max_lease_time));
62 
63  std::string encrypted_body;
64  if (!cipher->Encrypt(
65  "{\"path\" : \"" + path + "\", \"expiry\" : \"" + expiry + "\"}",
66  *secret, &encrypted_body)) {
67  return false;
68  }
69 
70  *session_token = Base64("{\"token_id\" : \"" + *public_token_id
71  + "\", \"blob\" : \"" + Base64(encrypted_body)
72  + "\"}");
73 
74  return true;
75 }
76 
81 bool GetTokenPublicId(const std::string &token, std::string *public_id) {
82  if (public_id == NULL) {
83  return false;
84  }
85 
86  std::string debased64_token;
87  if (!Debase64(token, &debased64_token)) {
88  return false;
89  }
90 
91  UniquePtr<JsonDocument> token_json(JsonDocument::Create(debased64_token));
92  if (!token_json.IsValid()) {
93  return false;
94  }
95 
96  const JSON *token_id = JsonDocument::SearchInObject(token_json->root(),
97  "token_id", JSON_STRING);
98  const JSON *blob = JsonDocument::SearchInObject(token_json->root(), "blob",
99  JSON_STRING);
100 
101  if (token_id == NULL || blob == NULL) {
102  return false;
103  }
104 
105  *public_id = token_id->string_value;
106 
107  return true;
108 }
109 
110 /*
111  * Check the validity of a session token using the associated secret
112  */
113 TokenCheckResult CheckToken(const std::string &token, const std::string &secret,
114  std::string *lease_path) {
115  if (!lease_path) {
116  return kInvalid;
117  }
118 
119  std::string debased64_token;
120  if (!Debase64(token, &debased64_token)) {
121  return kInvalid;
122  }
123 
124  UniquePtr<JsonDocument> token_json(JsonDocument::Create(debased64_token));
125  if (!token_json.IsValid()) {
126  return kInvalid;
127  }
128 
129  const JSON *token_id = JsonDocument::SearchInObject(token_json->root(),
130  "token_id", JSON_STRING);
131  const JSON *blob = JsonDocument::SearchInObject(token_json->root(), "blob",
132  JSON_STRING);
133  if (token_id == NULL || blob == NULL) {
134  return kInvalid;
135  }
136 
137  std::string debased64_secret;
138  if (!Debase64(secret, &debased64_secret)) {
139  return kInvalid;
140  }
142  if (!key.IsValid()) {
143  return kInvalid;
144  }
145 
146  std::string encrypted_body;
147  if (!Debase64(blob->string_value, &encrypted_body)) {
148  return kInvalid;
149  }
150 
151  std::string body;
152  if (!cipher::Cipher::Decrypt(encrypted_body, *key, &body)) {
153  return kInvalid;
154  }
155 
157  if (!token_json.IsValid()) {
158  return kInvalid;
159  }
160 
161  const JSON *path = JsonDocument::SearchInObject(body_json->root(), "path",
162  JSON_STRING);
163  const JSON *expiry = JsonDocument::SearchInObject(body_json->root(), "expiry",
164  JSON_STRING);
165  if (path == NULL || expiry == NULL) {
166  return kInvalid;
167  }
168 
169  // TODO(radu): can we still use monotonic time if the process restarts?
170  uint64_t expiry_time = String2Uint64(expiry->string_value);
171  const uint64_t current_time = platform_monotonic_time();
172  if (current_time > expiry_time) {
173  return kExpired;
174  }
175 
176  *lease_path = path->string_value;
177 
178  return kValid;
179 }
180 
181 } // namespace receiver
static bool Decrypt(const std::string &ciphertext, const Key &key, std::string *plaintext)
Definition: encrypt.cc:186
static JSON * SearchInObject(const JSON *json_object, const std::string &name, const json_type type)
static Cipher * Create(const Algorithms a)
Definition: encrypt.cc:157
std::string ToBase64() const
Definition: encrypt.cc:109
bool GenerateSessionToken(const std::string &key_id, const std::string &path, uint64_t max_lease_time, std::string *session_token, std::string *public_token_id, std::string *token_secret)
static Key * CreateRandomly(const unsigned size)
Definition: encrypt.cc:32
std::string StringifyUint(const uint64_t value)
Definition: string.cc:83
bool Debase64(const string &data, string *decoded)
Definition: string.cc:598
static JsonDocument * Create(const std::string &text)
uint64_t platform_monotonic_time()
bool GetTokenPublicId(const std::string &token, std::string *public_id)
TokenCheckResult CheckToken(const std::string &token, const std::string &secret, std::string *lease_path)
string Base64(const string &data)
Definition: string.cc:537
bool Encrypt(const std::string &plaintext, const Key &key, std::string *ciphertext)
Definition: encrypt.cc:170
uint64_t String2Uint64(const string &value)
Definition: string.cc:240
static Key * CreateFromString(const std::string &key)
Definition: encrypt.cc:77
struct json_value JSON
Definition: helper_allow.cc:11
const JSON * root() const
Definition: json_document.h:25