storage_directory.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. #include "platform.h"
  2. #include <errno.h>
  3. #include <stdint.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "crypto.h"
  7. #include "crypto_entropy.h"
  8. #include "netpacket.h"
  9. #include "netproto.h"
  10. #include "storage_internal.h"
  11. #include "sysendian.h"
  12. #include "tsnetwork.h"
  13. #include "warnp.h"
  14. #include "storage.h"
  15. struct directory_read_internal {
  16. /* General state information. */
  17. uint64_t machinenum;
  18. int done;
  19. NETPACKET_CONNECTION * NPC;
  20. /* Parameters used in directory read. */
  21. uint8_t class;
  22. int key;
  23. uint8_t start[32];
  24. uint8_t nonce[32];
  25. uint8_t * flist;
  26. size_t nfiles;
  27. size_t nfiles_alloc;
  28. };
  29. static sendpacket_callback callback_getnonce_send;
  30. static handlepacket_callback callback_getnonce_response;
  31. static handlepacket_callback callback_directory_response;
  32. /**
  33. * storage_directory_read(machinenum, class, key, flist, nfiles):
  34. * Fetch a sorted list of files in the specified class. If ${key} is 0, use
  35. * NETPACKET_DIRECTORY requests (using the read key); otherwise, use
  36. * NETPACKET_DIRECTORY_D requests (using the delete key). Return the list
  37. * and the number of files via ${flist} and ${nfiles} respectively.
  38. */
  39. int
  40. storage_directory_read(uint64_t machinenum, char class, int key,
  41. uint8_t ** flist, size_t * nfiles)
  42. {
  43. struct directory_read_internal C;
  44. /* Open netpacket connection. */
  45. if ((C.NPC = netpacket_open(USERAGENT)) == NULL)
  46. goto err0;
  47. /* Initialize structure. */
  48. C.machinenum = machinenum;
  49. C.done = 0;
  50. C.class = (uint8_t)class;
  51. C.key = key;
  52. memset(C.start, 0, 32);
  53. C.flist = NULL;
  54. C.nfiles = C.nfiles_alloc = 0;
  55. /* Ask the netpacket layer to send a request and get a response. */
  56. if (netpacket_op(C.NPC, callback_getnonce_send, &C))
  57. goto err2;
  58. /* Wait until we're done or we have failed. */
  59. if (network_spin(&C.done))
  60. goto err2;
  61. /* Return results. */
  62. *flist = C.flist;
  63. *nfiles = C.nfiles;
  64. /* Close netpacket connection. */
  65. if (netpacket_close(C.NPC))
  66. goto err1;
  67. /* Success! */
  68. return (0);
  69. err2:
  70. netpacket_close(C.NPC);
  71. err1:
  72. free(C.flist);
  73. err0:
  74. /* Failure! */
  75. return (-1);
  76. }
  77. static int
  78. callback_getnonce_send(void * cookie, NETPACKET_CONNECTION * NPC)
  79. {
  80. struct directory_read_internal * C = cookie;
  81. /* Ask the server to provide a transaction server nonce. */
  82. return (netpacket_transaction_getnonce(NPC, C->machinenum,
  83. callback_getnonce_response));
  84. }
  85. static int
  86. callback_getnonce_response(void * cookie, NETPACKET_CONNECTION * NPC,
  87. int status, uint8_t packettype, const uint8_t * packetbuf,
  88. size_t packetlen)
  89. {
  90. struct directory_read_internal * C = cookie;
  91. uint8_t cnonce[32];
  92. (void)packetlen; /* UNUSED */
  93. /* Handle read errors. */
  94. if (status != NETWORK_STATUS_OK) {
  95. netproto_printerr(status);
  96. goto err0;
  97. }
  98. /* Make sure we received the right type of packet. */
  99. if (packettype != NETPACKET_TRANSACTION_GETNONCE_RESPONSE)
  100. goto err1;
  101. /* Generate a random client nonce. */
  102. if (crypto_entropy_read(cnonce, 32))
  103. goto err0;
  104. /* Compute operation nonce. */
  105. if (crypto_hash_data_2(CRYPTO_KEY_HMAC_SHA256, packetbuf, 32,
  106. cnonce, 32, C->nonce)) {
  107. warn0("Programmer error: "
  108. "SHA256 should never fail");
  109. goto err0;
  110. }
  111. /* Send a directory read request. */
  112. if (netpacket_directory(NPC, C->machinenum, C->class, C->start,
  113. packetbuf, cnonce, C->key, callback_directory_response))
  114. goto err0;
  115. /* Success! */
  116. return (0);
  117. err1:
  118. netproto_printerr(NETPROTO_STATUS_PROTERR);
  119. err0:
  120. /* Failure! */
  121. return (-1);
  122. }
  123. static int
  124. callback_directory_response(void * cookie, NETPACKET_CONNECTION * NPC,
  125. int status, uint8_t packettype, const uint8_t * packetbuf,
  126. size_t packetlen)
  127. {
  128. struct directory_read_internal * C = cookie;
  129. uint8_t * flist_new;
  130. size_t nfiles;
  131. size_t file;
  132. int i;
  133. /* Handle read errors. */
  134. if (status != NETWORK_STATUS_OK) {
  135. netproto_printerr(status);
  136. goto err0;
  137. }
  138. /* Make sure we received the right type of packet. */
  139. if (packettype != NETPACKET_DIRECTORY_RESPONSE)
  140. goto err1;
  141. /* Verify packet hmac. */
  142. switch (netpacket_hmac_verify(packettype, C->nonce,
  143. packetbuf, packetlen - 32,
  144. (C->key == 0) ? CRYPTO_KEY_AUTH_GET : CRYPTO_KEY_AUTH_DELETE)) {
  145. case 1:
  146. goto err1;
  147. case -1:
  148. goto err0;
  149. }
  150. /* Parse nfiles field. */
  151. nfiles = be32dec(&packetbuf[34]);
  152. /* Sanity-check parameters. */
  153. if ((packetbuf[0] > 3) ||
  154. (packetbuf[1] != C->class) ||
  155. (memcmp(&packetbuf[2], C->start, 32) != 0) ||
  156. (nfiles > NETPACKET_DIRECTORY_RESPONSE_MAXFILES))
  157. goto err1;
  158. /* Sanity-check length. */
  159. if (packetlen != 70 + nfiles * 32)
  160. goto err1;
  161. /* Do we need to reallocate? */
  162. if (C->nfiles + nfiles > C->nfiles_alloc) {
  163. C->nfiles_alloc = 2 * C->nfiles + nfiles;
  164. if (C->nfiles_alloc > SIZE_MAX / 32) {
  165. errno = ENOMEM;
  166. goto err0;
  167. }
  168. if ((flist_new = malloc(C->nfiles_alloc * 32)) == NULL)
  169. goto err0;
  170. if (C->nfiles > 0)
  171. memcpy(flist_new, C->flist, C->nfiles * 32);
  172. free(C->flist);
  173. C->flist = flist_new;
  174. }
  175. /* Add files to list, while making sure that the files are ordered. */
  176. for (file = 0; file < nfiles; file++) {
  177. if (memcmp(C->start, &packetbuf[38 + file * 32], 32) > 0)
  178. goto err1;
  179. memcpy(C->start, &packetbuf[38 + file * 32], 32);
  180. memcpy(C->flist + (C->nfiles + file) * 32, C->start, 32);
  181. for (i = 31; i >= 0; i--)
  182. if (++(C->start[i]) != 0)
  183. break;
  184. }
  185. C->nfiles += nfiles;
  186. /* Are there more packets to come? */
  187. switch (packetbuf[0]) {
  188. case 0:
  189. /* No more files. */
  190. C->done = 1;
  191. break;
  192. case 1:
  193. /* More files to come. */
  194. if (netpacket_directory_readmore(NPC,
  195. callback_directory_response))
  196. goto err0;
  197. break;
  198. case 2:
  199. /* We need to send another request. */
  200. if (netpacket_op(NPC, callback_getnonce_send, C))
  201. goto err0;
  202. break;
  203. case 3:
  204. /* Insufficient funds. */
  205. warn0("Cannot read list of archive fragments: "
  206. "Account balance is not positive.");
  207. warn0("Please add more money to your tarsnap account");
  208. goto err0;
  209. }
  210. /* Success! */
  211. return (0);
  212. err1:
  213. netproto_printerr(NETPROTO_STATUS_PROTERR);
  214. err0:
  215. /* Failure! */
  216. return (-1);
  217. }