marshal.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. #ifndef PUTTY_MARSHAL_H
  2. #define PUTTY_MARSHAL_H
  3. #include "defs.h"
  4. #include <stdio.h>
  5. #include <stdarg.h>
  6. /*
  7. * A sort of 'abstract base class' or 'interface' or 'trait' which is
  8. * the common feature of all types that want to accept data formatted
  9. * using the SSH binary conventions of uint32, string, mpint etc.
  10. */
  11. struct BinarySink {
  12. void (*write)(BinarySink *sink, const void *data, size_t len);
  13. void (*writefmtv)(BinarySink *sink, const char *fmt, va_list ap);
  14. BinarySink *binarysink_;
  15. };
  16. /*
  17. * To define a structure type as a valid target for binary formatted
  18. * data, put 'BinarySink_IMPLEMENTATION' in its declaration, and when
  19. * an instance is set up, use 'BinarySink_INIT' to initialise the
  20. * 'base class' state, providing a function pointer to be the
  21. * implementation of the write() call above.
  22. */
  23. #define BinarySink_IMPLEMENTATION BinarySink binarysink_[1]
  24. #define BinarySink_INIT(obj, writefn) \
  25. ((obj)->binarysink_->write = (writefn), \
  26. (obj)->binarysink_->writefmtv = NULL, \
  27. (obj)->binarysink_->binarysink_ = (obj)->binarysink_)
  28. /*
  29. * To define a larger structure type as a valid BinarySink in such a
  30. * way that it will delegate the write method to some other object,
  31. * put 'BinarySink_DELEGATE_IMPLEMENTATION' in its declaration, and
  32. * when an instance is set up, use 'BinarySink_DELEGATE_INIT' to point
  33. * at the object it wants to delegate to.
  34. *
  35. * In such a delegated structure, you might sometimes want to have the
  36. * delegation stop being valid (e.g. it might be delegating to an
  37. * object that only sometimes exists). You can null out the delegate
  38. * pointer using BinarySink_DELEGATE_CLEAR.
  39. */
  40. #define BinarySink_DELEGATE_IMPLEMENTATION BinarySink *binarysink_
  41. #define BinarySink_DELEGATE_INIT(obj, othersink) \
  42. ((obj)->binarysink_ = BinarySink_UPCAST(othersink))
  43. #define BinarySink_DELEGATE_CLEAR(obj) ((obj)->binarysink_ = NULL)
  44. /*
  45. * The implementing type's write function will want to downcast its
  46. * 'BinarySink *' parameter back to the more specific type. Also,
  47. * sometimes you'll want to upcast a pointer to a particular
  48. * implementing type into an abstract 'BinarySink *' to pass to
  49. * generic subroutines not defined in this file. These macros do that
  50. * job.
  51. *
  52. * Importantly, BinarySink_UPCAST can also be applied to a BinarySink
  53. * * itself (and leaves it unchanged). That's achieved by a small
  54. * piece of C trickery: implementing structures and the BinarySink
  55. * structure itself both contain a field called binarysink_, but in
  56. * implementing objects it's a BinarySink[1] whereas in the abstract
  57. * type it's a 'BinarySink *' pointing back to the same structure,
  58. * meaning that you can say 'foo->binarysink_' in either case and get
  59. * a pointer type by different methods.
  60. */
  61. #define BinarySink_DOWNCAST(object, type) \
  62. TYPECHECK((object) == ((type *)0)->binarysink_, \
  63. ((type *)(((char *)(object)) - offsetof(type, binarysink_))))
  64. #define BinarySink_UPCAST(object) \
  65. TYPECHECK((object)->binarysink_ == (BinarySink *)0, \
  66. (object)->binarysink_)
  67. /*
  68. * If you structure-copy an object that's implementing BinarySink,
  69. * then that tricky self-pointer in its trait subobject will point to
  70. * the wrong place. You could call BinarySink_INIT again, but this
  71. * macro is terser and does all that's needed to fix up the copied
  72. * object.
  73. */
  74. #define BinarySink_COPIED(obj) \
  75. ((obj)->binarysink_->binarysink_ = (obj)->binarysink_)
  76. /*
  77. * The put_* macros are the main client to this system. Any structure
  78. * which implements the BinarySink 'trait' is valid for use as the
  79. * first parameter of any of these put_* macros.
  80. */
  81. /* Basic big-endian integer types. */
  82. #define put_byte(bs, val) \
  83. BinarySink_put_byte(BinarySink_UPCAST(bs), val)
  84. #define put_uint16(bs, val) \
  85. BinarySink_put_uint16(BinarySink_UPCAST(bs), val)
  86. #define put_uint32(bs, val) \
  87. BinarySink_put_uint32(BinarySink_UPCAST(bs), val)
  88. #define put_uint64(bs, val) \
  89. BinarySink_put_uint64(BinarySink_UPCAST(bs), val)
  90. /* SSH booleans, encoded as a single byte storing either 0 or 1. */
  91. #define put_bool(bs, val) \
  92. BinarySink_put_bool(BinarySink_UPCAST(bs), val)
  93. /* SSH strings, with a leading uint32 length field. 'stringz' is a
  94. * convenience function that takes an ordinary C zero-terminated
  95. * string as input. 'stringsb' takes a strbuf * as input, and
  96. * finalises it as a side effect (handy for multi-level marshalling in
  97. * which you use these same functions to format an inner blob of data
  98. * that then gets wrapped into a string container in an outer one). */
  99. #define put_string(bs, val, len) \
  100. BinarySink_put_string(BinarySink_UPCAST(bs),val,len)
  101. #define put_stringpl(bs, ptrlen) \
  102. BinarySink_put_stringpl(BinarySink_UPCAST(bs),ptrlen)
  103. #define put_stringz(bs, val) \
  104. BinarySink_put_stringz(BinarySink_UPCAST(bs), val)
  105. #define put_stringsb(bs, val) \
  106. BinarySink_put_stringsb(BinarySink_UPCAST(bs), val)
  107. /* Other string outputs: 'asciz' emits the string data directly into
  108. * the output including the terminating \0, and 'pstring' emits the
  109. * string in Pascal style with a leading _one_-byte length field.
  110. * pstring can fail if the string is too long. */
  111. #define put_asciz(bs, val) \
  112. BinarySink_put_asciz(BinarySink_UPCAST(bs), val)
  113. #define put_pstring(bs, val) \
  114. BinarySink_put_pstring(BinarySink_UPCAST(bs), val)
  115. /* Multiprecision integers, in both the SSH-1 and SSH-2 formats. */
  116. #define put_mp_ssh1(bs, val) \
  117. BinarySink_put_mp_ssh1(BinarySink_UPCAST(bs), val)
  118. #define put_mp_ssh2(bs, val) \
  119. BinarySink_put_mp_ssh2(BinarySink_UPCAST(bs), val)
  120. /* Padding with a specified byte. */
  121. #define put_padding(bs, len, padbyte) \
  122. BinarySink_put_padding(BinarySink_UPCAST(bs), len, padbyte)
  123. /* Fallback: just emit raw data bytes, using a syntax that matches the
  124. * rest of these macros. */
  125. #define put_data(bs, val, len) \
  126. BinarySink_put_data(BinarySink_UPCAST(bs), val, len)
  127. #define put_datapl(bs, pl) \
  128. BinarySink_put_datapl(BinarySink_UPCAST(bs), pl)
  129. #define put_dataz(bs, val) \
  130. BinarySink_put_datapl(BinarySink_UPCAST(bs), ptrlen_from_asciz(val))
  131. #define put_datalit(bs, val) \
  132. BinarySink_put_datapl(BinarySink_UPCAST(bs), PTRLEN_LITERAL(val))
  133. /* Emit printf-formatted data, with no terminator. */
  134. #define put_fmt(bs, ...) \
  135. BinarySink_put_fmt(BinarySink_UPCAST(bs), __VA_ARGS__)
  136. #define put_fmtv(bs, fmt, ap) \
  137. BinarySink_put_fmtv(BinarySink_UPCAST(bs), fmt, ap)
  138. /* More complicated function implemented in write_c_string_literal.c */
  139. #define put_c_string_literal(bs, str) \
  140. BinarySink_put_c_string_literal(BinarySink_UPCAST(bs), str)
  141. /* More complicated function implemented in encode_utf8.c */
  142. #define put_utf8_char(bs, c) \
  143. BinarySink_put_utf8_char(BinarySink_UPCAST(bs), c)
  144. /*
  145. * The underlying real C functions that implement most of those
  146. * macros. Generally you won't want to call these directly, because
  147. * they have such cumbersome names; you call the wrapper macros above
  148. * instead.
  149. *
  150. * A few functions whose wrapper macros are defined above are actually
  151. * declared in other headers, so as to guarantee that the
  152. * declaration(s) of their other parameter type(s) are in scope.
  153. */
  154. void BinarySink_put_data(BinarySink *, const void *data, size_t len);
  155. void BinarySink_put_datapl(BinarySink *, ptrlen);
  156. void BinarySink_put_padding(BinarySink *, size_t len, unsigned char padbyte);
  157. void BinarySink_put_byte(BinarySink *, unsigned char);
  158. void BinarySink_put_bool(BinarySink *, bool);
  159. void BinarySink_put_uint16(BinarySink *, unsigned long);
  160. void BinarySink_put_uint32(BinarySink *, unsigned long);
  161. void BinarySink_put_uint64(BinarySink *, uint64_t);
  162. void BinarySink_put_string(BinarySink *, const void *data, size_t len);
  163. void BinarySink_put_stringpl(BinarySink *, ptrlen);
  164. void BinarySink_put_stringz(BinarySink *, const char *str);
  165. void BinarySink_put_stringsb(BinarySink *, strbuf *);
  166. void BinarySink_put_asciz(BinarySink *, const char *str);
  167. bool BinarySink_put_pstring(BinarySink *, const char *str);
  168. void BinarySink_put_mp_ssh1(BinarySink *bs, mp_int *x);
  169. void BinarySink_put_mp_ssh2(BinarySink *bs, mp_int *x);
  170. void BinarySink_put_fmt(BinarySink *, const char *fmt, ...) PRINTF_LIKE(2, 3);
  171. void BinarySink_put_fmtv(BinarySink *, const char *fmt, va_list ap);
  172. void BinarySink_put_c_string_literal(BinarySink *, ptrlen);
  173. void BinarySink_put_utf8_char(BinarySink *, unsigned);
  174. /* ---------------------------------------------------------------------- */
  175. /*
  176. * A complementary trait structure for _un_-marshalling.
  177. *
  178. * This structure contains client-visible data fields rather than
  179. * methods, because that seemed more useful than leaving it totally
  180. * opaque. But it's still got the self-pointer system that will allow
  181. * the set of get_* macros to target one of these itself or any other
  182. * type that 'derives' from it. So, for example, an SSH packet
  183. * structure can act as a BinarySource while also having additional
  184. * fields like the packet type.
  185. */
  186. typedef enum BinarySourceError {
  187. BSE_NO_ERROR,
  188. BSE_OUT_OF_DATA,
  189. BSE_INVALID
  190. } BinarySourceError;
  191. struct BinarySource {
  192. /*
  193. * (data, len) is the data block being decoded. pos is the current
  194. * position within the block.
  195. */
  196. const void *data;
  197. size_t pos, len;
  198. /*
  199. * 'err' indicates whether a decoding error has happened at any
  200. * point. Once this has been set to something other than
  201. * BSE_NO_ERROR, it shouldn't be changed by any unmarshalling
  202. * function. So you can safely do a long sequence of get_foo()
  203. * operations and then test err just once at the end, rather than
  204. * having to conditionalise every single get.
  205. *
  206. * The unmarshalling functions should always return some value,
  207. * even if a decoding error occurs. Generally on error they'll
  208. * return zero (if numeric) or the empty string (if string-based),
  209. * or some other appropriate default value for more complicated
  210. * types.
  211. *
  212. * If the usual return value is dynamically allocated (e.g. a
  213. * bignum, or a normal C 'char *' string), then the error value is
  214. * also dynamic in the same way. So you have to free exactly the
  215. * same set of things whether or not there was a decoding error,
  216. * which simplifies exit paths - for example, you could call a big
  217. * pile of get_foo functions, then put the actual handling of the
  218. * results under 'if (!get_err(src))', and then free everything
  219. * outside that if.
  220. */
  221. BinarySourceError err;
  222. /*
  223. * Self-pointer for the implicit derivation trick, same as
  224. * BinarySink above.
  225. */
  226. BinarySource *binarysource_;
  227. };
  228. /*
  229. * Implementation macros, similar to BinarySink.
  230. */
  231. #define BinarySource_IMPLEMENTATION BinarySource binarysource_[1]
  232. static inline void BinarySource_INIT__(BinarySource *src, ptrlen data)
  233. {
  234. src->data = data.ptr;
  235. src->len = data.len;
  236. src->pos = 0;
  237. src->err = BSE_NO_ERROR;
  238. src->binarysource_ = src;
  239. }
  240. #define BinarySource_BARE_INIT_PL(obj, pl) \
  241. TYPECHECK(&(obj)->binarysource_ == (BinarySource **)0, \
  242. BinarySource_INIT__(obj, pl))
  243. #define BinarySource_BARE_INIT(obj, data_, len_) \
  244. BinarySource_BARE_INIT_PL(obj, make_ptrlen(data_, len_))
  245. #define BinarySource_INIT_PL(obj, pl) \
  246. TYPECHECK(&(obj)->binarysource_ == (BinarySource (*)[1])0, \
  247. BinarySource_INIT__(BinarySource_UPCAST(obj), pl))
  248. #define BinarySource_INIT(obj, data_, len_) \
  249. BinarySource_INIT_PL(obj, make_ptrlen(data_, len_))
  250. #define BinarySource_DOWNCAST(object, type) \
  251. TYPECHECK((object) == ((type *)0)->binarysource_, \
  252. ((type *)(((char *)(object)) - offsetof(type, binarysource_))))
  253. #define BinarySource_UPCAST(object) \
  254. TYPECHECK((object)->binarysource_ == (BinarySource *)0, \
  255. (object)->binarysource_)
  256. #define BinarySource_COPIED(obj) \
  257. ((obj)->binarysource_->binarysource_ = (obj)->binarysource_)
  258. #define BinarySource_REWIND_TO(src, pos) \
  259. BinarySource_REWIND_TO__((src)->binarysource_, pos)
  260. #define BinarySource_REWIND(src) \
  261. BinarySource_REWIND_TO__((src)->binarysource_, 0)
  262. #define get_data(src, len) \
  263. BinarySource_get_data(BinarySource_UPCAST(src), len)
  264. #define get_byte(src) \
  265. BinarySource_get_byte(BinarySource_UPCAST(src))
  266. #define get_bool(src) \
  267. BinarySource_get_bool(BinarySource_UPCAST(src))
  268. #define get_uint16(src) \
  269. BinarySource_get_uint16(BinarySource_UPCAST(src))
  270. #define get_uint32(src) \
  271. BinarySource_get_uint32(BinarySource_UPCAST(src))
  272. #define get_uint64(src) \
  273. BinarySource_get_uint64(BinarySource_UPCAST(src))
  274. #define get_string(src) \
  275. BinarySource_get_string(BinarySource_UPCAST(src))
  276. #define get_asciz(src) \
  277. BinarySource_get_asciz(BinarySource_UPCAST(src))
  278. #define get_chars(src, include) \
  279. BinarySource_get_chars(BinarySource_UPCAST(src), include)
  280. #define get_nonchars(src, exclude) \
  281. BinarySource_get_nonchars(BinarySource_UPCAST(src), exclude)
  282. #define get_chomped_line(src) \
  283. BinarySource_get_chomped_line(BinarySource_UPCAST(src))
  284. #define get_pstring(src) \
  285. BinarySource_get_pstring(BinarySource_UPCAST(src))
  286. #define get_mp_ssh1(src) \
  287. BinarySource_get_mp_ssh1(BinarySource_UPCAST(src))
  288. #define get_mp_ssh2(src) \
  289. BinarySource_get_mp_ssh2(BinarySource_UPCAST(src))
  290. #define get_rsa_ssh1_pub(src, rsa, order) \
  291. BinarySource_get_rsa_ssh1_pub(BinarySource_UPCAST(src), rsa, order)
  292. #define get_rsa_ssh1_priv(src, rsa) \
  293. BinarySource_get_rsa_ssh1_priv(BinarySource_UPCAST(src), rsa)
  294. #define get_rsa_ssh1_priv_agent(src) \
  295. BinarySource_get_rsa_ssh1_priv_agent(BinarySource_UPCAST(src))
  296. #define get_err(src) (BinarySource_UPCAST(src)->err)
  297. #define get_avail(src) (BinarySource_UPCAST(src)->len - \
  298. BinarySource_UPCAST(src)->pos)
  299. #define get_ptr(src) \
  300. ((const void *)( \
  301. (const unsigned char *)(BinarySource_UPCAST(src)->data) + \
  302. BinarySource_UPCAST(src)->pos))
  303. ptrlen BinarySource_get_data(BinarySource *, size_t);
  304. unsigned char BinarySource_get_byte(BinarySource *);
  305. bool BinarySource_get_bool(BinarySource *);
  306. unsigned BinarySource_get_uint16(BinarySource *);
  307. unsigned long BinarySource_get_uint32(BinarySource *);
  308. uint64_t BinarySource_get_uint64(BinarySource *);
  309. ptrlen BinarySource_get_string(BinarySource *);
  310. const char *BinarySource_get_asciz(BinarySource *);
  311. ptrlen BinarySource_get_chars(BinarySource *, const char *include_set);
  312. ptrlen BinarySource_get_nonchars(BinarySource *, const char *exclude_set);
  313. ptrlen BinarySource_get_chomped_line(BinarySource *);
  314. ptrlen BinarySource_get_pstring(BinarySource *);
  315. mp_int *BinarySource_get_mp_ssh1(BinarySource *src);
  316. mp_int *BinarySource_get_mp_ssh2(BinarySource *src);
  317. void BinarySource_REWIND_TO__(BinarySource *src, size_t pos);
  318. /*
  319. * A couple of useful standard BinarySink implementations, which live
  320. * as sensibly here as anywhere else: one that makes a BinarySink
  321. * whose effect is to write to a stdio stream, and one whose effect is
  322. * to append to a bufchain.
  323. */
  324. struct stdio_sink {
  325. FILE *fp;
  326. BinarySink_IMPLEMENTATION;
  327. };
  328. struct bufchain_sink {
  329. bufchain *ch;
  330. BinarySink_IMPLEMENTATION;
  331. };
  332. struct buffer_sink {
  333. char *out;
  334. size_t space;
  335. bool overflowed;
  336. BinarySink_IMPLEMENTATION;
  337. };
  338. void stdio_sink_init(stdio_sink *sink, FILE *fp);
  339. void bufchain_sink_init(bufchain_sink *sink, bufchain *ch);
  340. void buffer_sink_init(buffer_sink *sink, void *buffer, size_t len);
  341. #endif /* PUTTY_MARSHAL_H */