encode.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. /* encode.c - ber output encoding routines */
  2. /* $OpenLDAP$ */
  3. /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  4. *
  5. * Copyright 1998-2024 The OpenLDAP Foundation.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted only as authorized by the OpenLDAP
  10. * Public License.
  11. *
  12. * A copy of this license is available in the file LICENSE in the
  13. * top-level directory of the distribution or, alternatively, at
  14. * <http://www.OpenLDAP.org/license.html>.
  15. */
  16. /* Portions Copyright (c) 1990 Regents of the University of Michigan.
  17. * All rights reserved.
  18. *
  19. * Redistribution and use in source and binary forms are permitted
  20. * provided that this notice is preserved and that due credit is given
  21. * to the University of Michigan at Ann Arbor. The name of the University
  22. * may not be used to endorse or promote products derived from this
  23. * software without specific prior written permission. This software
  24. * is provided ``as is'' without express or implied warranty.
  25. */
  26. /* ACKNOWLEDGEMENTS:
  27. * This work was originally developed by the University of Michigan
  28. * (as part of U-MICH LDAP).
  29. */
  30. #include "portable.h"
  31. #include <ctype.h>
  32. #include <limits.h>
  33. #include <stdio.h>
  34. #include <ac/stdlib.h>
  35. #include <ac/stdarg.h>
  36. #include <ac/socket.h>
  37. #include <ac/string.h>
  38. #include "lber-int.h"
  39. #define OCTET_SIZE(type) ((ber_len_t) (sizeof(type)*CHAR_BIT + 7) / 8)
  40. #define TAGBUF_SIZE OCTET_SIZE(ber_tag_t)
  41. #define LENBUF_SIZE (1 + OCTET_SIZE(ber_len_t))
  42. #define HEADER_SIZE (TAGBUF_SIZE + LENBUF_SIZE)
  43. /*
  44. * BER element size constrains:
  45. *
  46. * - We traditionally support a length of max 0xffffffff. However
  47. * some functions return an int length so that is their max.
  48. * MAXINT_BERSIZE is the max for those functions.
  49. *
  50. * - MAXINT_BERSIZE must fit in MAXINT_BERSIZE_OCTETS octets.
  51. *
  52. * - sizeof(ber_elem_size_t) is normally MAXINT_BERSIZE_OCTETS:
  53. * Big enough for MAXINT_BERSIZE, but not more. (Larger wastes
  54. * space in the working encoding and DER encoding of a sequence
  55. * or set. Smaller further limits sizes near a sequence/set.)
  56. *
  57. * ber_len_t is mostly unrelated to this. Which may be for the best,
  58. * since it is also used for lengths of data that are never encoded.
  59. */
  60. #define MAXINT_BERSIZE \
  61. (INT_MAX>0xffffffffUL ? (ber_len_t) 0xffffffffUL : INT_MAX-HEADER_SIZE)
  62. #define MAXINT_BERSIZE_OCTETS 4
  63. typedef ber_uint_t ber_elem_size_t; /* normally 32 bits */
  64. /* Prepend tag to ptr, which points to the end of a tag buffer */
  65. static unsigned char *
  66. ber_prepend_tag( unsigned char *ptr, ber_tag_t tag )
  67. {
  68. do {
  69. *--ptr = (unsigned char) tag & 0xffU;
  70. } while ( (tag >>= 8) != 0 );
  71. return ptr;
  72. }
  73. /* Prepend ber length to ptr, which points to the end of a length buffer */
  74. static unsigned char *
  75. ber_prepend_len( unsigned char *ptr, ber_len_t len )
  76. {
  77. /*
  78. * short len if it's less than 128 - one byte giving the len,
  79. * with bit 8 0.
  80. * long len otherwise - one byte with bit 8 set, giving the
  81. * length of the length, followed by the length itself.
  82. */
  83. *--ptr = (unsigned char) len & 0xffU;
  84. if ( len >= 0x80 ) {
  85. unsigned char *endptr = ptr--;
  86. while ( (len >>= 8) != 0 ) {
  87. *ptr-- = (unsigned char) len & 0xffU;
  88. }
  89. *ptr = (unsigned char) (endptr - ptr) + 0x80U;
  90. }
  91. return ptr;
  92. }
  93. /* out->bv_len should be the buffer size on input */
  94. int
  95. ber_encode_oid( BerValue *in, BerValue *out )
  96. {
  97. unsigned char *der;
  98. unsigned long val1, val;
  99. int i, j, len;
  100. char *ptr, *end, *inend;
  101. assert( in != NULL );
  102. assert( out != NULL );
  103. if ( !out->bv_val || out->bv_len < in->bv_len/2 )
  104. return -1;
  105. der = (unsigned char *) out->bv_val;
  106. ptr = in->bv_val;
  107. inend = ptr + in->bv_len;
  108. /* OIDs start with <0-1>.<0-39> or 2.<any>, DER-encoded 40*val1+val2 */
  109. if ( !isdigit( (unsigned char) *ptr )) return -1;
  110. val1 = strtoul( ptr, &end, 10 );
  111. if ( end == ptr || val1 > 2 ) return -1;
  112. if ( *end++ != '.' || !isdigit( (unsigned char) *end )) return -1;
  113. val = strtoul( end, &ptr, 10 );
  114. if ( ptr == end ) return -1;
  115. if ( val > (val1 < 2 ? 39 : LBER_OID_COMPONENT_MAX - 80) ) return -1;
  116. val += val1 * 40;
  117. for (;;) {
  118. if ( ptr > inend ) return -1;
  119. /* Write the OID component little-endian, then reverse it */
  120. len = 0;
  121. do {
  122. der[len++] = (val & 0xff) | 0x80;
  123. } while ( (val >>= 7) != 0 );
  124. der[0] &= 0x7f;
  125. for ( i = 0, j = len; i < --j; i++ ) {
  126. unsigned char tmp = der[i];
  127. der[i] = der[j];
  128. der[j] = tmp;
  129. }
  130. der += len;
  131. if ( ptr == inend )
  132. break;
  133. if ( *ptr++ != '.' ) return -1;
  134. if ( !isdigit( (unsigned char) *ptr )) return -1;
  135. val = strtoul( ptr, &end, 10 );
  136. if ( end == ptr || val > LBER_OID_COMPONENT_MAX ) return -1;
  137. ptr = end;
  138. }
  139. out->bv_len = (char *)der - out->bv_val;
  140. return 0;
  141. }
  142. static int
  143. ber_put_int_or_enum(
  144. BerElement *ber,
  145. ber_int_t num,
  146. ber_tag_t tag )
  147. {
  148. ber_uint_t unum;
  149. unsigned char sign, data[TAGBUF_SIZE+1 + OCTET_SIZE(ber_int_t)], *ptr;
  150. sign = 0;
  151. unum = num; /* Bit fiddling should be done with unsigned values */
  152. if ( num < 0 ) {
  153. sign = 0xffU;
  154. unum = ~unum;
  155. }
  156. for ( ptr = &data[sizeof(data) - 1] ;; unum >>= 8 ) {
  157. *ptr-- = (sign ^ (unsigned char) unum) & 0xffU;
  158. if ( unum < 0x80 ) /* top bit at *ptr is sign bit */
  159. break;
  160. }
  161. *ptr = (unsigned char) (&data[sizeof(data) - 1] - ptr); /* length */
  162. ptr = ber_prepend_tag( ptr, tag );
  163. return ber_write( ber, (char *) ptr, &data[sizeof(data)] - ptr, 0 );
  164. }
  165. int
  166. ber_put_enum(
  167. BerElement *ber,
  168. ber_int_t num,
  169. ber_tag_t tag )
  170. {
  171. if ( tag == LBER_DEFAULT ) {
  172. tag = LBER_ENUMERATED;
  173. }
  174. return ber_put_int_or_enum( ber, num, tag );
  175. }
  176. int
  177. ber_put_int(
  178. BerElement *ber,
  179. ber_int_t num,
  180. ber_tag_t tag )
  181. {
  182. if ( tag == LBER_DEFAULT ) {
  183. tag = LBER_INTEGER;
  184. }
  185. return ber_put_int_or_enum( ber, num, tag );
  186. }
  187. int
  188. ber_put_ostring(
  189. BerElement *ber,
  190. LDAP_CONST char *str,
  191. ber_len_t len,
  192. ber_tag_t tag )
  193. {
  194. int rc;
  195. unsigned char header[HEADER_SIZE], *ptr;
  196. if ( tag == LBER_DEFAULT ) {
  197. tag = LBER_OCTETSTRING;
  198. }
  199. if ( len > MAXINT_BERSIZE ) {
  200. return -1;
  201. }
  202. ptr = ber_prepend_len( &header[sizeof(header)], len );
  203. ptr = ber_prepend_tag( ptr, tag );
  204. rc = ber_write( ber, (char *) ptr, &header[sizeof(header)] - ptr, 0 );
  205. if ( rc >= 0 && ber_write( ber, str, len, 0 ) >= 0 ) {
  206. /* length(tag + length + contents) */
  207. return rc + (int) len;
  208. }
  209. return -1;
  210. }
  211. int
  212. ber_put_berval(
  213. BerElement *ber,
  214. struct berval *bv,
  215. ber_tag_t tag )
  216. {
  217. if( bv == NULL || bv->bv_len == 0 ) {
  218. return ber_put_ostring( ber, "", (ber_len_t) 0, tag );
  219. }
  220. return ber_put_ostring( ber, bv->bv_val, bv->bv_len, tag );
  221. }
  222. int
  223. ber_put_string(
  224. BerElement *ber,
  225. LDAP_CONST char *str,
  226. ber_tag_t tag )
  227. {
  228. assert( str != NULL );
  229. return ber_put_ostring( ber, str, strlen( str ), tag );
  230. }
  231. int
  232. ber_put_bitstring(
  233. BerElement *ber,
  234. LDAP_CONST char *str,
  235. ber_len_t blen /* in bits */,
  236. ber_tag_t tag )
  237. {
  238. int rc;
  239. ber_len_t len;
  240. unsigned char unusedbits, header[HEADER_SIZE + 1], *ptr;
  241. if ( tag == LBER_DEFAULT ) {
  242. tag = LBER_BITSTRING;
  243. }
  244. unusedbits = (unsigned char) -blen & 7;
  245. len = blen / 8 + (unusedbits != 0); /* (blen+7)/8 without overflow */
  246. if ( len >= MAXINT_BERSIZE ) {
  247. return -1;
  248. }
  249. header[sizeof(header) - 1] = unusedbits;
  250. ptr = ber_prepend_len( &header[sizeof(header) - 1], len + 1 );
  251. ptr = ber_prepend_tag( ptr, tag );
  252. rc = ber_write( ber, (char *) ptr, &header[sizeof(header)] - ptr, 0 );
  253. if ( rc >= 0 && ber_write( ber, str, len, 0 ) >= 0 ) {
  254. /* length(tag + length + unused bit count + bitstring) */
  255. return rc + (int) len;
  256. }
  257. return -1;
  258. }
  259. int
  260. ber_put_null( BerElement *ber, ber_tag_t tag )
  261. {
  262. unsigned char data[TAGBUF_SIZE + 1], *ptr;
  263. if ( tag == LBER_DEFAULT ) {
  264. tag = LBER_NULL;
  265. }
  266. data[sizeof(data) - 1] = 0; /* length */
  267. ptr = ber_prepend_tag( &data[sizeof(data) - 1], tag );
  268. return ber_write( ber, (char *) ptr, &data[sizeof(data)] - ptr, 0 );
  269. }
  270. int
  271. ber_put_boolean(
  272. BerElement *ber,
  273. ber_int_t boolval,
  274. ber_tag_t tag )
  275. {
  276. unsigned char data[TAGBUF_SIZE + 2], *ptr;
  277. if ( tag == LBER_DEFAULT )
  278. tag = LBER_BOOLEAN;
  279. data[sizeof(data) - 1] = boolval ? 0xff : 0;
  280. data[sizeof(data) - 2] = 1; /* length */
  281. ptr = ber_prepend_tag( &data[sizeof(data) - 2], tag );
  282. return ber_write( ber, (char *) ptr, &data[sizeof(data)] - ptr, 0 );
  283. }
  284. /* Max number of length octets in a sequence or set, normally 5 */
  285. #define SOS_LENLEN (1 + (sizeof(ber_elem_size_t) > MAXINT_BERSIZE_OCTETS ? \
  286. (ber_len_t) sizeof(ber_elem_size_t) : MAXINT_BERSIZE_OCTETS))
  287. /* Header of incomplete sequence or set */
  288. typedef struct seqorset_header {
  289. char xtagbuf[TAGBUF_SIZE + 1]; /* room for tag + len(tag or len) */
  290. union {
  291. ber_elem_size_t offset; /* enclosing sequence/set */
  292. char padding[SOS_LENLEN-1]; /* for final length encoding */
  293. } next_sos;
  294. # define SOS_TAG_END(header) ((unsigned char *) &(header).next_sos - 1)
  295. } Seqorset_header;
  296. /* Start a sequence or set */
  297. static int
  298. ber_start_seqorset(
  299. BerElement *ber,
  300. ber_tag_t tag )
  301. {
  302. /*
  303. * Write the tag and SOS_LENLEN octets reserved for length, to ber.
  304. * For now, length octets = (tag length, previous ber_sos_inner).
  305. *
  306. * Update ber_sos_inner and the write-cursor ber_sos_ptr. ber_ptr
  307. * will not move until the outermost sequence or set is complete.
  308. */
  309. Seqorset_header header;
  310. unsigned char *headptr;
  311. ber_len_t taglen, headlen;
  312. char *dest, **p;
  313. assert( ber != NULL );
  314. assert( LBER_VALID( ber ) );
  315. if ( ber->ber_sos_ptr == NULL ) { /* outermost sequence/set? */
  316. header.next_sos.offset = 0;
  317. p = &ber->ber_ptr;
  318. } else {
  319. if ( (ber_len_t) -1 > (ber_elem_size_t) -1 ) {
  320. if ( ber->ber_sos_inner > (ber_elem_size_t) -1 )
  321. return -1;
  322. }
  323. header.next_sos.offset = ber->ber_sos_inner;
  324. p = &ber->ber_sos_ptr;
  325. }
  326. headptr = ber_prepend_tag( SOS_TAG_END(header), tag );
  327. *SOS_TAG_END(header) = taglen = SOS_TAG_END(header) - headptr;
  328. headlen = taglen + SOS_LENLEN;
  329. /* As ber_write(,headptr,headlen,) except update ber_sos_ptr, not *p */
  330. if ( headlen > (ber_len_t) (ber->ber_end - *p) ) {
  331. if ( ber_realloc( ber, headlen ) != 0 )
  332. return -1;
  333. }
  334. dest = *p;
  335. AC_MEMCPY( dest, headptr, headlen );
  336. ber->ber_sos_ptr = dest + headlen;
  337. ber->ber_sos_inner = dest + taglen - ber->ber_buf;
  338. /*
  339. * Do not return taglen + SOS_LENLEN here - then ber_put_seqorset()
  340. * should return lenlen - SOS_LENLEN + len, which can be < 0.
  341. */
  342. return 0;
  343. }
  344. int
  345. ber_start_seq( BerElement *ber, ber_tag_t tag )
  346. {
  347. if ( tag == LBER_DEFAULT ) {
  348. tag = LBER_SEQUENCE;
  349. }
  350. return ber_start_seqorset( ber, tag );
  351. }
  352. int
  353. ber_start_set( BerElement *ber, ber_tag_t tag )
  354. {
  355. if ( tag == LBER_DEFAULT ) {
  356. tag = LBER_SET;
  357. }
  358. return ber_start_seqorset( ber, tag );
  359. }
  360. /* End a sequence or set */
  361. static int
  362. ber_put_seqorset( BerElement *ber )
  363. {
  364. Seqorset_header header;
  365. unsigned char *lenptr; /* length octets in the sequence/set */
  366. ber_len_t len; /* length(contents) */
  367. ber_len_t xlen; /* len + length(length) */
  368. assert( ber != NULL );
  369. assert( LBER_VALID( ber ) );
  370. if ( ber->ber_sos_ptr == NULL ) return -1;
  371. lenptr = (unsigned char *) ber->ber_buf + ber->ber_sos_inner;
  372. xlen = ber->ber_sos_ptr - (char *) lenptr;
  373. if ( xlen > MAXINT_BERSIZE + SOS_LENLEN ) {
  374. return -1;
  375. }
  376. /* Extract sequence/set information from length octets */
  377. memcpy( SOS_TAG_END(header), lenptr, SOS_LENLEN );
  378. /* Store length, and close gap of leftover reserved length octets */
  379. len = xlen - SOS_LENLEN;
  380. if ( !(ber->ber_options & LBER_USE_DER) ) {
  381. int i;
  382. lenptr[0] = SOS_LENLEN - 1 + 0x80; /* length(length)-1 */
  383. for( i = SOS_LENLEN; --i > 0; len >>= 8 ) {
  384. lenptr[i] = len & 0xffU;
  385. }
  386. } else {
  387. unsigned char *p = ber_prepend_len( lenptr + SOS_LENLEN, len );
  388. ber_len_t unused = p - lenptr;
  389. if ( unused != 0 ) {
  390. /* length(length) < the reserved SOS_LENLEN bytes */
  391. xlen -= unused;
  392. AC_MEMCPY( lenptr, p, xlen );
  393. ber->ber_sos_ptr = (char *) lenptr + xlen;
  394. }
  395. }
  396. ber->ber_sos_inner = header.next_sos.offset;
  397. if ( header.next_sos.offset == 0 ) { /* outermost sequence/set? */
  398. /* The ber_ptr is at the set/seq start - move it to the end */
  399. ber->ber_ptr = ber->ber_sos_ptr;
  400. ber->ber_sos_ptr = NULL;
  401. }
  402. return xlen + *SOS_TAG_END(header); /* lenlen + len + taglen */
  403. }
  404. int
  405. ber_put_seq( BerElement *ber )
  406. {
  407. return ber_put_seqorset( ber );
  408. }
  409. int
  410. ber_put_set( BerElement *ber )
  411. {
  412. return ber_put_seqorset( ber );
  413. }
  414. /* N tag */
  415. static ber_tag_t lber_int_null = 0;
  416. /* VARARGS */
  417. int
  418. ber_printf( BerElement *ber, LDAP_CONST char *fmt, ... )
  419. {
  420. va_list ap;
  421. char *s, **ss;
  422. struct berval *bv, **bvp;
  423. int rc;
  424. ber_int_t i;
  425. ber_len_t len;
  426. assert( ber != NULL );
  427. assert( fmt != NULL );
  428. assert( LBER_VALID( ber ) );
  429. va_start( ap, fmt );
  430. for ( rc = 0; *fmt && rc != -1; fmt++ ) {
  431. switch ( *fmt ) {
  432. case '!': { /* hook */
  433. BEREncodeCallback *f;
  434. void *p;
  435. ber->ber_usertag = 0;
  436. f = va_arg( ap, BEREncodeCallback * );
  437. p = va_arg( ap, void * );
  438. rc = (*f)( ber, p );
  439. if ( ber->ber_usertag ) {
  440. goto next;
  441. }
  442. } break;
  443. case 'b': /* boolean */
  444. i = va_arg( ap, ber_int_t );
  445. rc = ber_put_boolean( ber, i, ber->ber_tag );
  446. break;
  447. case 'i': /* int */
  448. i = va_arg( ap, ber_int_t );
  449. rc = ber_put_int( ber, i, ber->ber_tag );
  450. break;
  451. case 'e': /* enumeration */
  452. i = va_arg( ap, ber_int_t );
  453. rc = ber_put_enum( ber, i, ber->ber_tag );
  454. break;
  455. case 'n': /* null */
  456. rc = ber_put_null( ber, ber->ber_tag );
  457. break;
  458. case 'N': /* Debug NULL */
  459. rc = 0;
  460. if( lber_int_null != 0 ) {
  461. /* Insert NULL to ensure peer ignores unknown tags */
  462. rc = ber_put_null( ber, lber_int_null );
  463. }
  464. break;
  465. case 'o': /* octet string (non-null terminated) */
  466. s = va_arg( ap, char * );
  467. len = va_arg( ap, ber_len_t );
  468. rc = ber_put_ostring( ber, s, len, ber->ber_tag );
  469. break;
  470. case 'O': /* berval octet string */
  471. bv = va_arg( ap, struct berval * );
  472. if( bv == NULL ) break;
  473. rc = ber_put_berval( ber, bv, ber->ber_tag );
  474. break;
  475. case 's': /* string */
  476. s = va_arg( ap, char * );
  477. rc = ber_put_string( ber, s, ber->ber_tag );
  478. break;
  479. case 'B': /* bit string */
  480. case 'X': /* bit string (deprecated) */
  481. s = va_arg( ap, char * );
  482. len = va_arg( ap, ber_len_t ); /* in bits */
  483. rc = ber_put_bitstring( ber, s, len, ber->ber_tag );
  484. break;
  485. case 't': /* tag for the next element */
  486. ber->ber_tag = va_arg( ap, ber_tag_t );
  487. goto next;
  488. case 'v': /* vector of strings */
  489. if ( (ss = va_arg( ap, char ** )) == NULL )
  490. break;
  491. for ( i = 0; ss[i] != NULL; i++ ) {
  492. if ( (rc = ber_put_string( ber, ss[i],
  493. ber->ber_tag )) == -1 )
  494. break;
  495. }
  496. break;
  497. case 'V': /* sequences of strings + lengths */
  498. if ( (bvp = va_arg( ap, struct berval ** )) == NULL )
  499. break;
  500. for ( i = 0; bvp[i] != NULL; i++ ) {
  501. if ( (rc = ber_put_berval( ber, bvp[i],
  502. ber->ber_tag )) == -1 )
  503. break;
  504. }
  505. break;
  506. case 'W': /* BerVarray */
  507. if ( (bv = va_arg( ap, BerVarray )) == NULL )
  508. break;
  509. for ( i = 0; bv[i].bv_val != NULL; i++ ) {
  510. if ( (rc = ber_put_berval( ber, &bv[i],
  511. ber->ber_tag )) == -1 )
  512. break;
  513. }
  514. break;
  515. case '{': /* begin sequence */
  516. rc = ber_start_seq( ber, ber->ber_tag );
  517. break;
  518. case '}': /* end sequence */
  519. rc = ber_put_seqorset( ber );
  520. break;
  521. case '[': /* begin set */
  522. rc = ber_start_set( ber, ber->ber_tag );
  523. break;
  524. case ']': /* end set */
  525. rc = ber_put_seqorset( ber );
  526. break;
  527. default:
  528. if( ber->ber_debug ) {
  529. ber_log_printf( LDAP_DEBUG_ANY, ber->ber_debug,
  530. "ber_printf: unknown fmt %c\n", *fmt );
  531. }
  532. rc = -1;
  533. break;
  534. }
  535. ber->ber_tag = LBER_DEFAULT;
  536. next:;
  537. }
  538. va_end( ap );
  539. return rc;
  540. }