You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1310 lines
33 KiB

1 year ago
6 years ago
6 years ago
4 years ago
4 years ago
4 years ago
4 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
4 years ago
6 years ago
4 years ago
6 years ago
4 years ago
6 years ago
4 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
3 years ago
3 years ago
6 years ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
9 months ago
  1. /**
  2. * @file map_asn1.c
  3. * @brief map asn1 to pEp structs and back
  4. * @license GNU General Public License 3.0 - see LICENSE.txt
  5. */
  6. #include "pEp_internal.h"
  7. #include "map_asn1.h"
  8. #include "message_codec.h"
  9. /* Expand to a statement checking that the given expression evaluates to a
  10. non-NULL result, first using an assert and then an explicit check in C. If
  11. the check fails branch to the given label. */
  12. #define CHECK_NON_NULLITY_OR_GOTO(expr, label) \
  13. do \
  14. { \
  15. assert(expr); \
  16. if (! (expr)) \
  17. goto label; \
  18. } \
  19. while (false)
  20. /* Same as CHECK_NON_NULLITY_OR_GOTO, but in case of failure return the given
  21. expression (evaluated only once after the check) instead of branching. */
  22. #define CHECK_NON_NULLITY_OR_RETURN(expr, result) \
  23. do \
  24. { \
  25. assert(expr); \
  26. if (! (expr)) \
  27. return (result); \
  28. } \
  29. while (false)
  30. /* Expand to a statement which:
  31. - reallocates a new heap buffer of the given size, (as if with realloc),
  32. updating the given pointer lvalue;
  33. - jumps to the given label in case of allocation failure.
  34. The expansion may evaluate parameters multiple times. */
  35. #define ALLOCATE_OR_GOTO(lvalue_pointer, size, label) \
  36. do \
  37. { \
  38. /* Free any previous buffer, and reset to NULL. This is necessary \
  39. for correct deallocation in case of allocation errors later. */ \
  40. if ((lvalue_pointer) != NULL) { \
  41. free (lvalue_pointer); \
  42. lvalue_pointer = NULL; \
  43. } \
  44. (lvalue_pointer) = calloc (1, (size)); \
  45. if ((lvalue_pointer) == NULL) \
  46. goto label; \
  47. } \
  48. while (false)
  49. PIdentity_t *PIdentity_from_Struct(
  50. const pEp_identity *ident,
  51. PIdentity_t *result
  52. )
  53. {
  54. bool allocated = !result;
  55. CHECK_NON_NULLITY_OR_RETURN (ident, NULL);
  56. if (allocated)
  57. result = (PIdentity_t *) calloc(1, sizeof(PIdentity_t));
  58. CHECK_NON_NULLITY_OR_RETURN (result, NULL);
  59. if (ident->address) {
  60. int r = OCTET_STRING_fromBuf(&result->address, ident->address, -1);
  61. if (r)
  62. goto error;
  63. }
  64. if (! EMPTYSTR (ident->fpr)) {
  65. ALLOCATE_OR_GOTO (result->fpr, sizeof (Hash_t), error);
  66. if (OCTET_STRING_fromString(result->fpr, ident->fpr))
  67. goto error;
  68. }
  69. if (ident->user_id) {
  70. int r = OCTET_STRING_fromBuf(&result->user_id, ident->user_id, -1);
  71. if (r)
  72. goto error;
  73. }
  74. if (! EMPTYSTR (ident->username)) {
  75. ALLOCATE_OR_GOTO (result->username, sizeof (PString_t), error);
  76. int r = OCTET_STRING_fromBuf(result->username, ident->username, -1);
  77. if (r)
  78. goto error;
  79. }
  80. if (ident->comm_type != PEP_ct_unknown) {
  81. result->comm_type = ident->comm_type;
  82. }
  83. ALLOCATE_OR_GOTO (result->lang, sizeof (ISO639_1_t), error);
  84. if (! EMPTYSTR (ident->lang)) {
  85. int r = OCTET_STRING_fromBuf(result->lang, ident->lang, 2);
  86. assert(r == 0);
  87. if(r != 0)
  88. goto error;
  89. }
  90. else {
  91. int r = OCTET_STRING_fromBuf(result->lang, "en", 2);
  92. assert(r == 0);
  93. if(r != 0)
  94. goto error;
  95. }
  96. return result;
  97. error:
  98. if (allocated)
  99. ASN_STRUCT_FREE(asn_DEF_PIdentity, result);
  100. return NULL;
  101. }
  102. pEp_identity *PIdentity_to_Struct(PIdentity_t *ident, pEp_identity *result)
  103. {
  104. bool allocated = !result;
  105. assert(ident);
  106. if (!ident)
  107. return NULL;
  108. if (allocated)
  109. result = new_identity(NULL, NULL, NULL, NULL);
  110. CHECK_NON_NULLITY_OR_RETURN (result, NULL);
  111. result->address = strndup((char *) ident->address.buf,
  112. ident->address.size);
  113. CHECK_NON_NULLITY_OR_GOTO (result->address, enomem);
  114. if (ident->fpr && ! EMPTYSTR (ident->fpr->buf)) {
  115. result->fpr = strndup((char *) ident->fpr->buf, ident->fpr->size);
  116. CHECK_NON_NULLITY_OR_GOTO (result->fpr, enomem);
  117. }
  118. result->user_id = strndup((char *) ident->user_id.buf,
  119. ident->user_id.size);
  120. CHECK_NON_NULLITY_OR_GOTO (result->user_id, enomem);
  121. if (ident->username && ! EMPTYSTR (ident->username->buf)) {
  122. result->username = strndup((char *) ident->username->buf,
  123. ident->username->size);
  124. CHECK_NON_NULLITY_OR_GOTO (result->username, enomem);
  125. }
  126. result->comm_type = (PEP_comm_type) ident->comm_type;
  127. if (ident->lang && ident->lang->size == 2) {
  128. result->lang[0] = ident->lang->buf[0];
  129. result->lang[1] = ident->lang->buf[1];
  130. result->lang[2] = 0;
  131. }
  132. return result;
  133. enomem:
  134. if (allocated)
  135. free_identity(result);
  136. return NULL;
  137. }
  138. PIdentityList_t *PIdentityList_from_identity_list(
  139. const identity_list *list,
  140. PIdentityList_t *result
  141. )
  142. {
  143. bool allocated = !result;
  144. if (!(list && list->ident))
  145. return NULL;
  146. if (allocated) {
  147. result = (PIdentityList_t *) calloc(1, sizeof(PIdentityList_t));
  148. assert(result);
  149. if (!result)
  150. return NULL;
  151. }
  152. else {
  153. asn_sequence_empty(result);
  154. }
  155. for (const identity_list *l = list; l && l->ident; l=l->next) {
  156. PIdentity_t *ident = PIdentity_from_Struct(l->ident, NULL);
  157. if (ASN_SEQUENCE_ADD(&result->list, ident)) {
  158. ASN_STRUCT_FREE(asn_DEF_PIdentity, ident);
  159. goto enomem;
  160. }
  161. }
  162. return result;
  163. enomem:
  164. if (allocated)
  165. ASN_STRUCT_FREE(asn_DEF_PIdentityList, result);
  166. return NULL;
  167. }
  168. identity_list *PIdentityList_to_identity_list(PIdentityList_t *list, identity_list *result)
  169. {
  170. bool allocated = !result;
  171. assert(list);
  172. if (!list)
  173. return NULL;
  174. if (allocated)
  175. result = new_identity_list(NULL);
  176. if (!result)
  177. return NULL;
  178. identity_list *r = result;
  179. for (int i=0; i<list->list.count; i++) {
  180. pEp_identity *ident = PIdentity_to_Struct(list->list.array[i], NULL);
  181. r = identity_list_add(r, ident);
  182. if (!r)
  183. goto enomem;
  184. }
  185. return result;
  186. enomem:
  187. if (allocated)
  188. free_identity_list(result);
  189. return NULL;
  190. }
  191. Identity_t *Identity_from_Struct(
  192. const pEp_identity *ident,
  193. Identity_t *result
  194. )
  195. {
  196. bool allocated = !result;
  197. assert(ident);
  198. if (!ident)
  199. return NULL;
  200. if (allocated)
  201. result = (Identity_t *) calloc(1, sizeof(Identity_t));
  202. assert(result);
  203. if (!result)
  204. return NULL;
  205. if (ident->address) {
  206. int r = OCTET_STRING_fromBuf(&result->address, ident->address, -1);
  207. if (r)
  208. goto enomem;
  209. }
  210. if (ident->fpr) {
  211. if (OCTET_STRING_fromString(&result->fpr, ident->fpr))
  212. goto enomem;
  213. }
  214. if (ident->user_id) {
  215. int r = OCTET_STRING_fromBuf(&result->user_id, ident->user_id, -1);
  216. if (r)
  217. goto enomem;
  218. }
  219. if (ident->username) {
  220. int r = OCTET_STRING_fromBuf(&result->username, ident->username, -1);
  221. if (r)
  222. goto enomem;
  223. }
  224. if (ident->comm_type != PEP_ct_unknown) {
  225. result->comm_type = ident->comm_type;
  226. }
  227. if (! EMPTYSTR(ident->lang)) {
  228. int r = OCTET_STRING_fromBuf(&result->lang, ident->lang, 2);
  229. assert(r == 0);
  230. if(r != 0)
  231. goto enomem;
  232. }
  233. else {
  234. int r = OCTET_STRING_fromBuf(&result->lang, "en", 2);
  235. assert(r == 0);
  236. if(r != 0)
  237. goto enomem;
  238. }
  239. return result;
  240. enomem:
  241. if (allocated)
  242. ASN_STRUCT_FREE(asn_DEF_Identity, result);
  243. return NULL;
  244. }
  245. pEp_identity *Identity_to_Struct(Identity_t *ident, pEp_identity *result)
  246. {
  247. bool allocated = !result;
  248. assert(ident);
  249. if (!ident)
  250. return NULL;
  251. if (allocated)
  252. result = new_identity(NULL, NULL, NULL, NULL);
  253. if (!result)
  254. return NULL;
  255. result->address = strndup((char *) ident->address.buf,
  256. ident->address.size);
  257. assert(result->address);
  258. if (!result->address)
  259. goto enomem;
  260. result->fpr = strndup((char *) ident->fpr.buf, ident->fpr.size);
  261. assert(result->fpr);
  262. if (!result->fpr)
  263. goto enomem;
  264. result->user_id = strndup((char *) ident->user_id.buf,
  265. ident->user_id.size);
  266. assert(result->user_id);
  267. if (!result->user_id)
  268. goto enomem;
  269. result->username = strndup((char *) ident->username.buf,
  270. ident->username.size);
  271. assert(result->username);
  272. if (!result->username)
  273. goto enomem;
  274. result->comm_type = (PEP_comm_type) ident->comm_type;
  275. if (ident->lang.size == 2) {
  276. result->lang[0] = ident->lang.buf[0];
  277. result->lang[1] = ident->lang.buf[1];
  278. result->lang[2] = 0;
  279. }
  280. return result;
  281. enomem:
  282. if (allocated)
  283. free_identity(result);
  284. return NULL;
  285. }
  286. IdentityList_t *IdentityList_from_identity_list(
  287. const identity_list *list,
  288. IdentityList_t *result
  289. )
  290. {
  291. bool allocated = !result;
  292. if (!(list && list->ident))
  293. return NULL;
  294. if (allocated) {
  295. result = (IdentityList_t *) calloc(1, sizeof(IdentityList_t));
  296. assert(result);
  297. if (!result)
  298. return NULL;
  299. }
  300. else {
  301. asn_sequence_empty(result);
  302. }
  303. for (const identity_list *l = list; l && l->ident; l=l->next) {
  304. Identity_t *ident = Identity_from_Struct(l->ident, NULL);
  305. if (ASN_SEQUENCE_ADD(&result->list, ident)) {
  306. ASN_STRUCT_FREE(asn_DEF_Identity, ident);
  307. goto enomem;
  308. }
  309. }
  310. return result;
  311. enomem:
  312. if (allocated)
  313. ASN_STRUCT_FREE(asn_DEF_IdentityList, result);
  314. return NULL;
  315. }
  316. identity_list *IdentityList_to_identity_list(IdentityList_t *list, identity_list *result)
  317. {
  318. bool allocated = !result;
  319. assert(list);
  320. if (!list)
  321. return NULL;
  322. if (allocated)
  323. result = new_identity_list(NULL);
  324. if (!result)
  325. return NULL;
  326. identity_list *r = result;
  327. for (int i=0; i<list->list.count; i++) {
  328. pEp_identity *ident = Identity_to_Struct(list->list.array[i], NULL);
  329. r = identity_list_add(r, ident);
  330. if (!r)
  331. goto enomem;
  332. }
  333. return result;
  334. enomem:
  335. if (allocated)
  336. free_identity_list(result);
  337. return NULL;
  338. }
  339. PStringPair_t *PStringPair_from_Struct(
  340. const stringpair_t *value,
  341. PStringPair_t *result
  342. )
  343. {
  344. bool allocated = !result;
  345. assert(value);
  346. if (!value)
  347. return NULL;
  348. if (allocated)
  349. result = (PStringPair_t *) calloc(1, sizeof(PStringPair_t));
  350. assert(result);
  351. if (!result)
  352. return NULL;
  353. if (value->key) {
  354. int r = OCTET_STRING_fromBuf(&result->key, value->key, -1);
  355. if (r)
  356. goto enomem;
  357. }
  358. if (value->value) {
  359. int r = OCTET_STRING_fromBuf(&result->value, value->value, -1);
  360. if (r)
  361. goto enomem;
  362. }
  363. return result;
  364. enomem:
  365. if (allocated)
  366. ASN_STRUCT_FREE(asn_DEF_PStringPair, result);
  367. return NULL;
  368. }
  369. stringpair_t *PStringPair_to_Struct(PStringPair_t *value)
  370. {
  371. assert(value);
  372. if (!value)
  373. return NULL;
  374. stringpair_t *result = (stringpair_t *) calloc(1, sizeof(stringpair_t));
  375. assert(result);
  376. if (!result)
  377. goto enomem;
  378. result->key = strndup((char *) value->key.buf,
  379. value->key.size);
  380. assert(result->key);
  381. if (!result->key)
  382. goto enomem;
  383. result->value = strndup((char *) value->value.buf,
  384. value->value.size);
  385. assert(result->value);
  386. if (!result->value)
  387. goto enomem;
  388. return result;
  389. enomem:
  390. free_stringpair(result);
  391. return NULL;
  392. }
  393. PStringPairList_t *PStringPairList_from_stringpair_list(
  394. const stringpair_list_t *list,
  395. PStringPairList_t *result
  396. )
  397. {
  398. bool allocated = !result;
  399. assert(list);
  400. if (!(list && list->value))
  401. return NULL;
  402. if (allocated) {
  403. result = (PStringPairList_t *) calloc(1, sizeof(PStringPairList_t));
  404. assert(result);
  405. if (!result)
  406. return NULL;
  407. }
  408. else {
  409. asn_sequence_empty(result);
  410. }
  411. for (const stringpair_list_t *l = list; l && l->value; l=l->next) {
  412. PStringPair_t *value = PStringPair_from_Struct(l->value, NULL);
  413. if (ASN_SEQUENCE_ADD(&result->list, value)) {
  414. ASN_STRUCT_FREE(asn_DEF_PStringPair, value);
  415. goto enomem;
  416. }
  417. }
  418. return result;
  419. enomem:
  420. if (allocated)
  421. ASN_STRUCT_FREE(asn_DEF_PStringPairList, result);
  422. return NULL;
  423. }
  424. stringpair_list_t *PStringPairList_to_stringpair_list(
  425. PStringPairList_t *list,
  426. stringpair_list_t *result
  427. )
  428. {
  429. bool allocated = !result;
  430. assert(list);
  431. if (!list)
  432. return NULL;
  433. if (allocated)
  434. result = new_stringpair_list(NULL);
  435. if (!result)
  436. return NULL;
  437. stringpair_list_t *r = result;
  438. for (int i=0; i<list->list.count; i++) {
  439. stringpair_t *value = PStringPair_to_Struct(list->list.array[i]);
  440. r = stringpair_list_add(r, value);
  441. if (!r)
  442. goto enomem;
  443. }
  444. return result;
  445. enomem:
  446. if (allocated)
  447. free_stringpair_list(result);
  448. return NULL;
  449. }
  450. PStringList_t *PStringList_from_stringlist(
  451. const stringlist_t *list,
  452. PStringList_t *result
  453. )
  454. {
  455. bool allocated = !result;
  456. assert(list);
  457. if (!(list && list->value))
  458. return NULL;
  459. if (allocated) {
  460. result = (PStringList_t *) calloc(1, sizeof(PStringList_t));
  461. assert(result);
  462. if (!result)
  463. return NULL;
  464. }
  465. else {
  466. asn_sequence_empty(result);
  467. }
  468. for (const stringlist_t *l = list; l && l->value; l=l->next) {
  469. PString_t *element = (PString_t *) calloc(1, sizeof(PString_t));
  470. assert(element);
  471. if (!element)
  472. goto enomem;
  473. int r = OCTET_STRING_fromBuf(element, l->value, -1);
  474. if (r)
  475. goto enomem;
  476. if (ASN_SEQUENCE_ADD(&result->list, element)) {
  477. ASN_STRUCT_FREE(asn_DEF_PString, element);
  478. goto enomem;
  479. }
  480. }
  481. return result;
  482. enomem:
  483. if (allocated)
  484. ASN_STRUCT_FREE(asn_DEF_PStringList, result);
  485. return NULL;
  486. }
  487. stringlist_t *PStringList_to_stringlist(PStringList_t *list)
  488. {
  489. assert(list);
  490. if (!list)
  491. return NULL;
  492. stringlist_t *result = (stringlist_t *) calloc(1, sizeof(stringlist_t));
  493. assert(result);
  494. if (!result)
  495. goto enomem;
  496. stringlist_t *r = result;
  497. for (int i=0; i<list->list.count; i++) {
  498. char *s = strndup((char *) list->list.array[i]->buf,
  499. list->list.array[i]->size);
  500. assert(s);
  501. if (!s)
  502. goto enomem;
  503. r->value = s;
  504. if (i < list->list.count-1) {
  505. r->next = (stringlist_t *) calloc(1, sizeof(stringlist_t));
  506. assert(r->next);
  507. if (!r->next)
  508. goto enomem;
  509. r = r->next;
  510. }
  511. }
  512. return result;
  513. enomem:
  514. free_stringlist(result);
  515. return NULL;
  516. }
  517. PBlobList_t *PBlobList_from_bloblist(
  518. bloblist_t *list,
  519. PBlobList_t *result,
  520. bool copy,
  521. size_t max_blob_size
  522. )
  523. {
  524. bool allocated = !result;
  525. if (!max_blob_size)
  526. max_blob_size = SIZE_MAX;
  527. assert(list);
  528. if (!(list && list->value))
  529. return NULL;
  530. if (allocated) {
  531. result = (PBlobList_t *) calloc(1, sizeof(PBlobList_t));
  532. assert(result);
  533. if (!result)
  534. return NULL;
  535. }
  536. else {
  537. asn_sequence_empty(result);
  538. }
  539. size_t rest_blob_size = max_blob_size;
  540. for (bloblist_t *l = list; l && l->value; l=l->next) {
  541. PBlob_t *element = (PBlob_t *) calloc(1, sizeof(PBlob_t));
  542. assert(element);
  543. if (!element)
  544. goto enomem;
  545. int r = 0;
  546. if (l->size > rest_blob_size)
  547. goto enomem;
  548. rest_blob_size -= l->size;
  549. if (copy) {
  550. r = OCTET_STRING_fromBuf(&element->value, l->value, l->size);
  551. if (r)
  552. goto enomem;
  553. }
  554. else /* move */ {
  555. #if defined(__CHAR_BIT__) && __CHAR_BIT__ == 8
  556. element->value.buf = (uint8_t *) l->value;
  557. #else
  558. // FIXME: this is problematic on platforms with bytes != octets
  559. // we want this warning
  560. element->value.buf = l->value;
  561. #endif
  562. l->value = NULL;
  563. element->value.size = l->size;
  564. l->size = 0;
  565. }
  566. if (!EMPTYSTR(l->mime_type)) {
  567. PString_t *_mime_type = (PString_t *) calloc(1, sizeof(PString_t));
  568. assert(_mime_type);
  569. if (!_mime_type)
  570. goto enomem;
  571. r = OCTET_STRING_fromBuf(_mime_type, l->mime_type, -1);
  572. if (r)
  573. goto enomem;
  574. element->mime_type = _mime_type;
  575. }
  576. if (!EMPTYSTR(l->filename)) {
  577. PString_t *_filename = (PString_t *) calloc(1, sizeof(PString_t));
  578. assert(_filename);
  579. if (!_filename)
  580. goto enomem;
  581. r = OCTET_STRING_fromBuf(_filename, l->filename, -1);
  582. if (r)
  583. goto enomem;
  584. element->filename = _filename;
  585. }
  586. switch (l->disposition) {
  587. case PEP_CONTENT_DISP_ATTACHMENT:
  588. element->disposition = ContentDisposition_attachment;
  589. break;
  590. case PEP_CONTENT_DISP_INLINE:
  591. element->disposition = ContentDisposition_inline;
  592. break;
  593. case PEP_CONTENT_DISP_OTHER:
  594. element->disposition = ContentDisposition_other;
  595. break;
  596. default:
  597. assert(0); // should not happen; use default
  598. element->disposition = ContentDisposition_attachment;
  599. }
  600. if (ASN_SEQUENCE_ADD(&result->list, element)) {
  601. ASN_STRUCT_FREE(asn_DEF_PBlob, element);
  602. goto enomem;
  603. }
  604. }
  605. return result;
  606. enomem:
  607. if (allocated)
  608. ASN_STRUCT_FREE(asn_DEF_PBlobList, result);
  609. return NULL;
  610. }
  611. bloblist_t *PBlobList_to_bloblist(
  612. PBlobList_t *list,
  613. bloblist_t *result,
  614. bool copy,
  615. size_t max_blob_size
  616. )
  617. {
  618. bool allocated = !result;
  619. if (!max_blob_size)
  620. max_blob_size = SIZE_MAX;
  621. assert(list);
  622. if (!list)
  623. return NULL;
  624. if (allocated)
  625. result = new_bloblist(NULL, 0, NULL, NULL);
  626. if (!result)
  627. return NULL;
  628. size_t rest_blob_size = max_blob_size;
  629. bloblist_t *r = result;
  630. for (int i=0; i<list->list.count; i++) {
  631. // this should not happen
  632. assert(list->list.array[i]);
  633. if (!list->list.array[i])
  634. goto enomem;
  635. if (list->list.array[i]->value.size > rest_blob_size)
  636. goto enomem;
  637. rest_blob_size -= list->list.array[i]->value.size;
  638. char *_mime_type = NULL;
  639. if (list->list.array[i]->mime_type) {
  640. _mime_type = strndup((char *) list->list.array[i]->mime_type->buf,
  641. list->list.array[i]->mime_type->size);
  642. assert(_mime_type);
  643. if (!_mime_type)
  644. goto enomem;
  645. }
  646. char *_filename = NULL;
  647. if (list->list.array[i]->filename) {
  648. _filename = strndup((char *) list->list.array[i]->filename->buf,
  649. list->list.array[i]->filename->size);
  650. assert(_filename);
  651. if (!_filename)
  652. goto enomem;
  653. }
  654. #if defined(__CHAR_BIT__) && __CHAR_BIT__ == 8
  655. char *_data = (char *) list->list.array[i]->value.buf;
  656. #else
  657. // FIXME: this is problematic on platforms with bytes != octets
  658. // we want this warning
  659. char *_data = list->list.array[i]->value.buf;
  660. #endif
  661. if (copy) {
  662. _data = strndup(_data, list->list.array[i]->value.size);
  663. assert(_data);
  664. if (!_data)
  665. goto enomem;
  666. }
  667. // bloblist_add() has move semantics
  668. r = bloblist_add(r, _data, list->list.array[i]->value.size, _mime_type,
  669. _filename);
  670. if (!copy) {
  671. list->list.array[i]->value.buf = NULL;
  672. list->list.array[i]->value.size = 0;
  673. }
  674. if (!r)
  675. goto enomem;
  676. switch (list->list.array[i]->disposition) {
  677. case ContentDisposition_attachment:
  678. r->disposition = PEP_CONTENT_DISP_ATTACHMENT;
  679. break;
  680. case ContentDisposition_inline:
  681. r->disposition = PEP_CONTENT_DISP_INLINE;
  682. break;
  683. case ContentDisposition_other:
  684. r->disposition = PEP_CONTENT_DISP_OTHER;
  685. break;
  686. default:
  687. assert(0); // should not happen; use default
  688. r->disposition = PEP_CONTENT_DISP_ATTACHMENT;
  689. }
  690. }
  691. return result;
  692. enomem:
  693. if (allocated)
  694. free_bloblist(result);
  695. return NULL;
  696. }
  697. ASN1Message_t *ASN1Message_from_message(
  698. message *msg,
  699. ASN1Message_t *result,
  700. bool copy,
  701. size_t max_blob_size
  702. )
  703. {
  704. bool allocated = !result;
  705. if (!max_blob_size)
  706. max_blob_size = SIZE_MAX;
  707. assert(msg);
  708. if (!msg)
  709. return NULL;
  710. if (allocated) {
  711. result = (ASN1Message_t *) calloc(1, sizeof(ASN1Message_t));
  712. assert(result);
  713. if (!result)
  714. return NULL;
  715. }
  716. else {
  717. asn_sequence_empty(result);
  718. }
  719. // direction will be skipped on the line
  720. if (!EMPTYSTR(msg->id)) {
  721. PString_t *str = (PString_t *) calloc(1, sizeof(PString_t));
  722. assert(str);
  723. if (!str)
  724. goto enomem;
  725. int r = OCTET_STRING_fromBuf(str, msg->id, -1);
  726. if (r)
  727. goto enomem;
  728. result->id = str;
  729. }
  730. if (msg->sent) {
  731. GeneralizedTime_t *ts = asn_time2GT(NULL, msg->sent, 1);
  732. if (!ts)
  733. goto enomem;
  734. result->sent = ts;
  735. }
  736. if (msg->recv) {
  737. GeneralizedTime_t *ts = asn_time2GT(NULL, msg->recv, 1);
  738. if (!ts)
  739. goto enomem;
  740. result->recv = ts;
  741. }
  742. if (!msg->from) // from is not optional
  743. goto enomem;
  744. PIdentity_from_Struct(msg->from, &result->from);
  745. if (msg->to && msg->to->ident) {
  746. PIdentityList_t *l = PIdentityList_from_identity_list(msg->to, NULL);
  747. if (!l)
  748. goto enomem;
  749. result->to = l;
  750. }
  751. if (msg->cc && msg->cc->ident) {
  752. PIdentityList_t *l = PIdentityList_from_identity_list(msg->cc, NULL);
  753. if (!l)
  754. goto enomem;
  755. result->cc = l;
  756. }
  757. if (msg->bcc && msg->bcc->ident) {
  758. PIdentityList_t *l = PIdentityList_from_identity_list(msg->bcc, NULL);
  759. if (!l)
  760. goto enomem;
  761. result->bcc = l;
  762. }
  763. if (msg->recv_by) {
  764. PIdentity_t *i = PIdentity_from_Struct(msg->recv_by, NULL);
  765. if (!i)
  766. goto enomem;
  767. result->recv_by = i;
  768. }
  769. if (msg->reply_to && msg->reply_to->ident) {
  770. PIdentityList_t *l = PIdentityList_from_identity_list(msg->reply_to, NULL);
  771. if (!l)
  772. goto enomem;
  773. result->reply_to = l;
  774. }
  775. if (msg->in_reply_to && msg->in_reply_to->value) {
  776. PStringList_t *l = PStringList_from_stringlist(msg->in_reply_to, NULL);
  777. if (!l)
  778. goto enomem;
  779. result->in_reply_to = l;
  780. }
  781. if (msg->references && msg->references->value) {
  782. PStringList_t *l = PStringList_from_stringlist(msg->references, NULL);
  783. if (!l)
  784. goto enomem;
  785. result->references = l;
  786. }
  787. if (msg->keywords && msg->keywords->value) {
  788. PStringList_t *l = PStringList_from_stringlist(msg->keywords, NULL);
  789. if (!l)
  790. goto enomem;
  791. result->keywords = l;
  792. }
  793. if (!EMPTYSTR(msg->comments)) {
  794. PString_t *str = (PString_t *) calloc(1, sizeof(PString_t));
  795. assert(str);
  796. if (!str)
  797. goto enomem;
  798. int r = OCTET_STRING_fromBuf(str, msg->comments, -1);
  799. if (r)
  800. goto enomem;
  801. result->comments = str;
  802. }
  803. if (msg->opt_fields && msg->opt_fields->value) {
  804. PStringPairList_t *l = PStringPairList_from_stringpair_list(msg->opt_fields, NULL);
  805. if (!l)
  806. goto enomem;
  807. result->opt_fields = l;
  808. }
  809. if (!EMPTYSTR(msg->_sender_fpr)) {
  810. Hash_t *str = (Hash_t *) calloc(1, sizeof(Hash_t));
  811. assert(str);
  812. if (!str)
  813. goto enomem;
  814. int r = OCTET_STRING_fromBuf(str, msg->_sender_fpr, -1);
  815. if (r)
  816. goto enomem;
  817. result->sender_fpr = str;
  818. }
  819. if (!EMPTYSTR(msg->shortmsg)) {
  820. PString_t *str = (PString_t *) calloc(1, sizeof(PString_t));
  821. assert(str);
  822. if (!str)
  823. goto enomem;
  824. int r = OCTET_STRING_fromBuf(str, msg->shortmsg, -1);
  825. if (r)
  826. goto enomem;
  827. result->shortmsg = str;
  828. }
  829. size_t rest_blob_size = max_blob_size;
  830. if (!EMPTYSTR(msg->longmsg)) {
  831. PString_t *str = (PString_t *) calloc(1, sizeof(PString_t));
  832. assert(str);
  833. if (!str)
  834. goto enomem;
  835. if (copy) {
  836. int r = OCTET_STRING_fromBuf(str, msg->longmsg, -1);
  837. if (r)
  838. goto enomem;
  839. if (str->size > rest_blob_size)
  840. goto enomem;
  841. }
  842. else /* move */ {
  843. str->size = strlen(msg->longmsg);
  844. if (str->size > rest_blob_size)
  845. goto enomem;
  846. str->buf = (uint8_t *) msg->longmsg;
  847. msg->longmsg = NULL;
  848. }
  849. rest_blob_size -= str->size;
  850. result->longmsg = str;
  851. }
  852. if (!EMPTYSTR(msg->longmsg_formatted)) {
  853. PString_t *str = (PString_t *) calloc(1, sizeof(PString_t));
  854. assert(str);
  855. if (!str)
  856. goto enomem;
  857. if (copy) {
  858. int r = OCTET_STRING_fromBuf(str, msg->longmsg_formatted, -1);
  859. if (r)
  860. goto enomem;
  861. if (str->size > rest_blob_size)
  862. goto enomem;
  863. }
  864. else /* move */ {
  865. str->size = strlen(msg->longmsg_formatted);
  866. if (str->size > rest_blob_size)
  867. goto enomem;
  868. str->buf = (uint8_t *) msg->longmsg_formatted;
  869. msg->longmsg_formatted = NULL;
  870. }
  871. rest_blob_size -= str->size;
  872. result->longmsg_formatted = str;
  873. }
  874. if (msg->attachments && msg->attachments->value) {
  875. PBlobList_t *bl = PBlobList_from_bloblist(msg->attachments, NULL, copy,
  876. rest_blob_size);
  877. if (!bl)
  878. goto enomem;
  879. result->attachments = bl;
  880. }
  881. return result;
  882. enomem:
  883. if (allocated)
  884. free_ASN1Message(result);
  885. return NULL;
  886. }
  887. message *ASN1Message_to_message(
  888. ASN1Message_t *msg,
  889. message *result,
  890. bool copy,
  891. size_t max_blob_size
  892. )
  893. {
  894. bool allocated = !result;
  895. if (!max_blob_size)
  896. max_blob_size = SIZE_MAX;
  897. assert(msg);
  898. if (!msg)
  899. return NULL;
  900. if (allocated) {
  901. result = new_message(PEP_dir_incoming);
  902. if (!result)
  903. goto enomem;
  904. }
  905. if (msg->direction) {
  906. switch (*msg->direction) {
  907. case MessageDirection_incoming:
  908. result->dir = PEP_dir_incoming;
  909. break;
  910. case MessageDirection_outgoing:
  911. result->dir = PEP_dir_outgoing;
  912. break;
  913. default:
  914. assert(0);
  915. }
  916. }
  917. if (msg->id) {
  918. result->id = strndup((char *) msg->id->buf, msg->id->size);
  919. assert(result->id);
  920. if (!result->id)
  921. goto enomem;
  922. }
  923. if (msg->sent) {
  924. timestamp *_sent = new_timestamp(0);
  925. if (!_sent)
  926. goto enomem;
  927. if (asn_GT2time(msg->sent, _sent, 1) == -1)
  928. goto enomem;
  929. result->sent = _sent;
  930. }
  931. if (msg->recv) {
  932. timestamp *_recv = new_timestamp(0);
  933. if (!_recv)
  934. goto enomem;
  935. if (asn_GT2time(msg->recv, _recv, 1) == -1)
  936. goto enomem;
  937. result->recv = _recv;
  938. }
  939. // from is mandatory
  940. result->from = PIdentity_to_Struct(&msg->from, NULL);
  941. if (!result->from)
  942. goto enomem;
  943. if (msg->to) {
  944. identity_list *il = PIdentityList_to_identity_list(msg->to, NULL);
  945. if (!il)
  946. goto enomem;
  947. result->to = il;
  948. }
  949. if (msg->cc) {
  950. identity_list *il = PIdentityList_to_identity_list(msg->cc, NULL);
  951. if (!il)
  952. goto enomem;
  953. result->cc = il;
  954. }
  955. if (msg->bcc) {
  956. identity_list *il = PIdentityList_to_identity_list(msg->bcc, NULL);
  957. if (!il)
  958. goto enomem;
  959. result->bcc = il;
  960. }
  961. if (msg->recv_by) {
  962. pEp_identity *i = PIdentity_to_Struct(msg->recv_by, NULL);
  963. if (!i)
  964. goto enomem;
  965. result->recv_by = i;
  966. }
  967. if (msg->reply_to) {
  968. identity_list *il = PIdentityList_to_identity_list(msg->reply_to, NULL);
  969. if (!il)
  970. goto enomem;
  971. result->reply_to = il;
  972. }
  973. if (msg->in_reply_to) {
  974. stringlist_t *l = PStringList_to_stringlist(msg->in_reply_to);
  975. if (!l)
  976. goto enomem;
  977. result->in_reply_to = l;
  978. }
  979. if (msg->references) {
  980. stringlist_t *l = PStringList_to_stringlist(msg->references);
  981. if (!l)
  982. goto enomem;
  983. result->references = l;
  984. }
  985. if (msg->keywords) {
  986. stringlist_t *l = PStringList_to_stringlist(msg->keywords);
  987. if (!l)
  988. goto enomem;
  989. result->keywords = l;
  990. }
  991. if (msg->comments) {
  992. char *s = strndup((char *) msg->comments->buf, msg->comments->size);
  993. assert(s);
  994. if (!s)
  995. goto enomem;
  996. result->comments = s;
  997. }
  998. if (msg->opt_fields) {
  999. stringpair_list_t *l =
  1000. PStringPairList_to_stringpair_list(msg->opt_fields, NULL);
  1001. if (!l)
  1002. goto enomem;
  1003. result->opt_fields = l;
  1004. }
  1005. if (msg->sender_fpr) {
  1006. char *_sender_fpr = strndup((char *) msg->sender_fpr->buf,
  1007. msg->sender_fpr->size);
  1008. if (!_sender_fpr)
  1009. goto enomem;
  1010. result->_sender_fpr = _sender_fpr;
  1011. }
  1012. if (msg->shortmsg) {
  1013. char *s = strndup((char *) msg->shortmsg->buf, msg->shortmsg->size);
  1014. assert(s);
  1015. if (!s)
  1016. goto enomem;
  1017. result->shortmsg = s;
  1018. }
  1019. size_t rest_blob_size = max_blob_size;
  1020. if (msg->longmsg) {
  1021. if (msg->longmsg->size > rest_blob_size)
  1022. goto enomem;
  1023. char *s = NULL;
  1024. if (copy) {
  1025. s = strndup((char *) msg->longmsg->buf, msg->longmsg->size);
  1026. if (!s)
  1027. goto enomem;
  1028. rest_blob_size -= msg->longmsg->size;
  1029. }
  1030. else /* move */ {
  1031. s = (char *) msg->longmsg->buf;
  1032. msg->longmsg->buf = NULL;
  1033. rest_blob_size -= msg->longmsg->size;
  1034. msg->longmsg->size = 0;
  1035. }
  1036. result->longmsg = s;
  1037. }
  1038. if (msg->longmsg_formatted) {
  1039. if (msg->longmsg_formatted->size > rest_blob_size)
  1040. goto enomem;
  1041. char *s = NULL;
  1042. if (copy) {
  1043. s = strndup((char *) msg->longmsg_formatted->buf,
  1044. msg->longmsg_formatted->size);
  1045. if (!s)
  1046. goto enomem;
  1047. rest_blob_size -= msg->longmsg_formatted->size;
  1048. }
  1049. else /* move */ {
  1050. s = (char *) msg->longmsg_formatted->buf;
  1051. msg->longmsg_formatted->buf = NULL;
  1052. rest_blob_size -= msg->longmsg_formatted->size;
  1053. msg->longmsg_formatted->size = 0;
  1054. }
  1055. result->longmsg_formatted = s;
  1056. }
  1057. if (msg->attachments) {
  1058. bloblist_t *a = PBlobList_to_bloblist(msg->attachments, NULL, copy,
  1059. rest_blob_size);
  1060. if (!a)
  1061. goto enomem;
  1062. result->attachments = a;
  1063. }
  1064. return result;
  1065. enomem:
  1066. if (allocated)
  1067. free_message(result);
  1068. return NULL;
  1069. }