macaroon.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /*
  2. * macaroon.cpp
  3. *
  4. * Created on: Mar 19, 2017
  5. * Author: hp
  6. */
  7. #include "macaroon.h"
  8. #include <iostream>
  9. #include <string.h>
  10. #include <sodium/randombytes.h>
  11. #include <sodium/crypto_box.h>
  12. namespace c_macaroons {
  13. #include "macaroons.h"
  14. }
  15. namespace macaroons {
  16. macaroon::macaroon() {
  17. m = nullptr;
  18. }
  19. macaroon::macaroon(const macaroon& rhs) {
  20. c_macaroons::macaroon_returncode err = c_macaroons::MACAROON_SUCCESS;
  21. m = c_macaroons::macaroon_copy(rhs.m, &err);
  22. //TODO error handling
  23. }
  24. macaroon::macaroon(std::string location, std::string key, std::string id) {
  25. create(reinterpret_cast<const unsigned char*>(location.c_str()),
  26. location.size(),
  27. reinterpret_cast<const unsigned char*>(key.c_str()), key.size(),
  28. reinterpret_cast<const unsigned char*>(id.c_str()), id.size());
  29. }
  30. macaroon::macaroon(const char* location, size_t location_sz, const char* key,
  31. size_t key_sz, const char* id, size_t id_sz) {
  32. create(reinterpret_cast<const unsigned char*>(location), location_sz,
  33. reinterpret_cast<const unsigned char*>(key), key_sz,
  34. reinterpret_cast<const unsigned char*>(id), id_sz);
  35. }
  36. macaroon::macaroon(const unsigned char* location, size_t location_sz,
  37. const unsigned char* key, size_t key_sz, const unsigned char* id,
  38. size_t id_sz) {
  39. create(location, location_sz, key, key_sz, id, id_sz);
  40. }
  41. macaroon::macaroon(std::string data) {
  42. c_macaroons::macaroon_returncode err = c_macaroons::MACAROON_SUCCESS;
  43. m = c_macaroons::macaroon_deserialize((const unsigned char*) data.data(),
  44. data.size(), &err);
  45. if (err != c_macaroons::MACAROON_SUCCESS) {
  46. std::cerr << macaroon_error(err) << std::endl;
  47. }
  48. // TODO error handling
  49. }
  50. void macaroon::add_first_party_caveat(std::string predicate) {
  51. c_macaroons::macaroon_returncode err = c_macaroons::MACAROON_SUCCESS;
  52. c_macaroons::macaroon *n;
  53. n = c_macaroons::macaroon_add_first_party_caveat(m,
  54. reinterpret_cast<const unsigned char*>(predicate.c_str()),
  55. predicate.size(), &err);
  56. if (err != c_macaroons::MACAROON_SUCCESS) {
  57. std::cerr << macaroon_error(err) << std::endl;
  58. }
  59. c_macaroons::macaroon_destroy(m);
  60. m = n;
  61. // TODO error handling
  62. }
  63. void macaroon::add_first_party_caveat(const char* predicate,
  64. size_t predicate_sz) {
  65. c_macaroons::macaroon_returncode err = c_macaroons::MACAROON_SUCCESS;
  66. c_macaroons::macaroon *n;
  67. n = c_macaroons::macaroon_add_first_party_caveat(m,
  68. reinterpret_cast<const unsigned char*>(predicate), predicate_sz,
  69. &err);
  70. if (err != c_macaroons::MACAROON_SUCCESS) {
  71. std::cerr << macaroon_error(err) << std::endl;
  72. }
  73. c_macaroons::macaroon_destroy(m);
  74. m = n;
  75. // TODO error handling
  76. }
  77. void macaroon::add_third_party_caveat(std::string location, std::string key,
  78. std::string id) {
  79. c_macaroons::macaroon_returncode err = c_macaroons::MACAROON_SUCCESS;
  80. c_macaroons::macaroon *n;
  81. n = c_macaroons::macaroon_add_third_party_caveat(m,
  82. reinterpret_cast<const unsigned char*>(location.c_str()),
  83. location.size(),
  84. reinterpret_cast<const unsigned char*>(key.c_str()), key.size(),
  85. reinterpret_cast<const unsigned char*>(id.c_str()), id.size(),
  86. &err);
  87. if (err != c_macaroons::MACAROON_SUCCESS) {
  88. std::cerr << macaroon_error(err) << std::endl;
  89. }
  90. c_macaroons::macaroon_destroy(m);
  91. m = n;
  92. // TODO error handling
  93. }
  94. void macaroon::add_third_party_caveat(const char* location, size_t location_sz,
  95. const char *key, size_t key_sz, const char* id, size_t id_sz) {
  96. c_macaroons::macaroon_returncode err = c_macaroons::MACAROON_SUCCESS;
  97. c_macaroons::macaroon *n;
  98. n = c_macaroons::macaroon_add_third_party_caveat(m,
  99. reinterpret_cast<const unsigned char*>(location), location_sz,
  100. reinterpret_cast<const unsigned char*>(key), key_sz,
  101. reinterpret_cast<const unsigned char*>(id), id_sz, &err);
  102. if (err != c_macaroons::MACAROON_SUCCESS) {
  103. std::cerr << macaroon_error(err) << std::endl;
  104. }
  105. c_macaroons::macaroon_destroy(m);
  106. m = n;
  107. // TODO error handling
  108. }
  109. void macaroon::add_third_party_caveat(const char* location, size_t location_sz,
  110. const unsigned char *key, size_t key_sz, const unsigned char* id,
  111. size_t id_sz) {
  112. c_macaroons::macaroon_returncode err = c_macaroons::MACAROON_SUCCESS;
  113. c_macaroons::macaroon *n;
  114. n = c_macaroons::macaroon_add_third_party_caveat(m,
  115. reinterpret_cast<const unsigned char*>(location), location_sz, key,
  116. key_sz, id, id_sz, &err);
  117. if (err != c_macaroons::MACAROON_SUCCESS) {
  118. std::cerr << macaroon_error(err) << std::endl;
  119. }
  120. c_macaroons::macaroon_destroy(m);
  121. m = n;
  122. // TODO error handling
  123. }
  124. void macaroon::add_third_party_caveat_with_keypair(std::string location,
  125. unsigned char pk[crypto_box_PUBLICKEYBYTES],
  126. unsigned char sk[crypto_box_SECRETKEYBYTES]) {
  127. // secret for the remote
  128. unsigned char key[MACAROON_SUGGESTED_SECRET_LENGTH];
  129. randombytes(key, sizeof(key));
  130. unsigned char nonce[crypto_box_NONCEBYTES];
  131. randombytes(nonce, crypto_box_NONCEBYTES);
  132. unsigned char id[crypto_box_MACBYTES + sizeof(key) + sizeof(nonce)];
  133. crypto_box_easy(id, key, sizeof(key), nonce, pk, sk);
  134. memcpy(id + (crypto_box_MACBYTES + sizeof(key)), nonce, sizeof(nonce));
  135. add_third_party_caveat(location.c_str(), location.size(), key, sizeof(key),
  136. id, sizeof(id));
  137. }
  138. third_party_caveat_list macaroon::third_party_caveats() const {
  139. third_party_caveat_list ret;
  140. unsigned int num = c_macaroons::macaroon_num_third_party_caveats(m);
  141. for (unsigned int i = 0; i < num; ++i) {
  142. const unsigned char* location;
  143. size_t location_sz;
  144. const unsigned char* identifier;
  145. size_t identifier_sz;
  146. c_macaroons::macaroon_third_party_caveat(m, i, &location, &location_sz,
  147. &identifier, &identifier_sz);
  148. ret.push_back(
  149. { std::string(reinterpret_cast<const char*>(location),
  150. location_sz), std::string(
  151. reinterpret_cast<const char*>(identifier),
  152. identifier_sz) });
  153. }
  154. return ret;
  155. }
  156. macaroon macaroon::prepare_for_request(const macaroon& d) const {
  157. c_macaroons::macaroon_returncode err = c_macaroons::MACAROON_SUCCESS;
  158. macaroon ret;
  159. ret.m = c_macaroons::macaroon_prepare_for_request(m, d.m, &err);
  160. return ret;
  161. }
  162. std::string macaroon::inspect() const {
  163. c_macaroons::macaroon_returncode err = c_macaroons::MACAROON_SUCCESS;
  164. size_t sz = c_macaroons::macaroon_inspect_size_hint(m);
  165. char* data = new char[sz];
  166. c_macaroons::macaroon_inspect(m, data, sz, &err);
  167. std::string ret(data);
  168. delete[] data;
  169. return ret;
  170. // TODO error handling
  171. }
  172. std::string macaroon::serialize() const {
  173. c_macaroons::macaroon_returncode err = c_macaroons::MACAROON_SUCCESS;
  174. size_t sz = c_macaroons::macaroon_serialize_size_hint(m,
  175. c_macaroons::MACAROON_V1);
  176. unsigned char *data = new unsigned char[sz];
  177. c_macaroons::macaroon_serialize(m, c_macaroons::MACAROON_V1, data, sz,
  178. &err);
  179. std::string ret((const char*) data);
  180. delete[] data;
  181. return ret;
  182. // TODO error handling
  183. }
  184. bool macaroon::validate() const {
  185. if (c_macaroons::macaroon_validate(m) == 0)
  186. return true;
  187. return false;
  188. }
  189. std::string macaroon::location() const {
  190. const unsigned char* location = NULL;
  191. size_t location_sz = 0;
  192. c_macaroons::macaroon_location(m, &location, &location_sz);
  193. return std::string((const char*) location, location_sz);
  194. }
  195. std::string macaroon::identifier() const {
  196. const unsigned char* identifier = NULL;
  197. size_t identifier_sz = 0;
  198. c_macaroons::macaroon_identifier(m, &identifier, &identifier_sz);
  199. return std::string((const char*) identifier, identifier_sz);
  200. }
  201. macaroon macaroon::operator=(const macaroon& rhs) {
  202. c_macaroons::macaroon_returncode err;
  203. m = c_macaroons::macaroon_copy(rhs.m, &err);
  204. return *this;
  205. }
  206. bool macaroon::operator==(const macaroon& rhs) const {
  207. if (c_macaroons::macaroon_cmp(m, rhs.m) == 0)
  208. return true;
  209. return false;
  210. }
  211. void macaroon::create(const unsigned char* location, size_t location_sz,
  212. const unsigned char* key, size_t key_sz, const unsigned char* id,
  213. size_t id_sz) {
  214. c_macaroons::macaroon_returncode err;
  215. m = c_macaroons::macaroon_create(location, location_sz, key, key_sz, id,
  216. id_sz, &err);
  217. // TODO error handler
  218. }
  219. bool macaroon::has_third_party_caveats() const {
  220. if (macaroon_num_third_party_caveats(m) > 0)
  221. return true;
  222. return false;
  223. }
  224. macaroon::~macaroon() {
  225. c_macaroons::macaroon_destroy(m);
  226. }
  227. macaroon macaroon_discharge(std::string location, std::string secret,
  228. unsigned char pk[crypto_box_PUBLICKEYBYTES],
  229. unsigned char sk[crypto_box_SECRETKEYBYTES]) {
  230. unsigned char key[MACAROON_SUGGESTED_SECRET_LENGTH];
  231. const unsigned char *key_s =
  232. reinterpret_cast<const unsigned char*>(secret.data());
  233. const unsigned char *nonce =
  234. reinterpret_cast<const unsigned char*>(secret.data())
  235. + crypto_box_MACBYTES + sizeof(key);
  236. if (secret.size()
  237. != (sizeof(key) + crypto_box_MACBYTES + crypto_box_NONCEBYTES)) {
  238. throw authentication_exception("Macaroon secret size mismatch");
  239. }
  240. int rc = crypto_box_open_easy(key, key_s, crypto_box_MACBYTES + sizeof(key),
  241. nonce, pk, sk);
  242. return macaroon(reinterpret_cast<const unsigned char*>(location.c_str()),
  243. location.size(), key, sizeof(key),
  244. reinterpret_cast<const unsigned char*>(secret.c_str()),
  245. secret.size());
  246. }
  247. } // namespace macaroons