CernVM-FS  2.12.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  return true;
74 }
75 
80 bool GetTokenPublicId(const std::string& token, std::string* public_id) {
81  if (public_id == NULL) {
82  return false;
83  }
84 
85  std::string debased64_token;
86  if (!Debase64(token, &debased64_token)) {
87  return false;
88  }
89 
90  UniquePtr<JsonDocument> token_json(JsonDocument::Create(debased64_token));
91  if (!token_json.IsValid()) {
92  return false;
93  }
94 
95  const JSON* token_id =
96  JsonDocument::SearchInObject(token_json->root(), "token_id", JSON_STRING);
97  const JSON* blob =
98  JsonDocument::SearchInObject(token_json->root(), "blob", JSON_STRING);
99 
100  if (token_id == NULL || blob == NULL) {
101  return false;
102  }
103 
104  *public_id = token_id->string_value;
105 
106  return true;
107 }
108 
109 /*
110  * Check the validity of a session token using the associated secret
111  */
112 TokenCheckResult CheckToken(const std::string& token, const std::string& secret,
113  std::string* lease_path) {
114  if (!lease_path) {
115  return kInvalid;
116  }
117 
118  std::string debased64_token;
119  if (!Debase64(token, &debased64_token)) {
120  return kInvalid;
121  }
122 
123  UniquePtr<JsonDocument> token_json(JsonDocument::Create(debased64_token));
124  if (!token_json.IsValid()) {
125  return kInvalid;
126  }
127 
128  const JSON* token_id =
129  JsonDocument::SearchInObject(token_json->root(), "token_id", JSON_STRING);
130  const JSON* blob =
131  JsonDocument::SearchInObject(token_json->root(), "blob", JSON_STRING);
132  if (token_id == NULL || blob == NULL) {
133  return kInvalid;
134  }
135 
136  std::string debased64_secret;
137  if (!Debase64(secret, &debased64_secret)) {
138  return kInvalid;
139  }
141  if (!key.IsValid()) {
142  return kInvalid;
143  }
144 
145  std::string encrypted_body;
146  if (!Debase64(blob->string_value, &encrypted_body)) {
147  return kInvalid;
148  }
149 
150  std::string body;
151  if (!cipher::Cipher::Decrypt(encrypted_body, *key, &body)) {
152  return kInvalid;
153  }
154 
156  if (!token_json.IsValid()) {
157  return kInvalid;
158  }
159 
160  const JSON* path =
161  JsonDocument::SearchInObject(body_json->root(), "path", JSON_STRING);
162  const JSON* expiry =
163  JsonDocument::SearchInObject(body_json->root(), "expiry", JSON_STRING);
164  if (path == NULL || expiry == NULL) {
165  return kInvalid;
166  }
167 
168  // TODO(radu): can we still use monotonic time if the process restarts?
169  uint64_t expiry_time = String2Uint64(expiry->string_value);
170  const uint64_t current_time = platform_monotonic_time();
171  if (current_time > expiry_time) {
172  return kExpired;
173  }
174 
175  *lease_path = path->string_value;
176 
177  return kValid;
178 }
179 
180 } // namespace receiver
static bool Decrypt(const std::string &ciphertext, const Key &key, std::string *plaintext)
Definition: encrypt.cc:189
static JSON * SearchInObject(const JSON *json_object, const std::string &name, const json_type type)
static Cipher * Create(const Algorithms a)
Definition: encrypt.cc:158
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:84
bool Debase64(const string &data, string *decoded)
Definition: string.cc:582
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:522
bool Encrypt(const std::string &plaintext, const Key &key, std::string *ciphertext)
Definition: encrypt.cc:171
uint64_t String2Uint64(const string &value)
Definition: string.cc:246
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