PageRenderTime 59ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/src/src/pdkim/pdkim.c

https://gitlab.com/Exim/exim
C | 1905 lines | 1508 code | 226 blank | 171 comment | 604 complexity | 190d2cae0c54b6e91d7100f16b7e485f MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * PDKIM - a RFC4871 (DKIM) implementation
  3. *
  4. * Copyright (C) 2009 - 2012 Tom Kistner <tom@duncanthrax.net>
  5. *
  6. * http://duncanthrax.net/pdkim/
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program; if not, write to the Free Software Foundation, Inc.,
  20. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. */
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include <ctype.h>
  26. #include "pdkim.h"
  27. #include "sha1.h"
  28. #include "sha2.h"
  29. #include "rsa.h"
  30. #include "base64.h"
  31. #define PDKIM_SIGNATURE_VERSION "1"
  32. #define PDKIM_PUB_RECORD_VERSION "DKIM1"
  33. #define PDKIM_MAX_HEADER_LEN 65536
  34. #define PDKIM_MAX_HEADERS 512
  35. #define PDKIM_MAX_BODY_LINE_LEN 16384
  36. #define PDKIM_DNS_TXT_MAX_NAMELEN 1024
  37. #define PDKIM_DEFAULT_SIGN_HEADERS "From:Sender:Reply-To:Subject:Date:"\
  38. "Message-ID:To:Cc:MIME-Version:Content-Type:"\
  39. "Content-Transfer-Encoding:Content-ID:"\
  40. "Content-Description:Resent-Date:Resent-From:"\
  41. "Resent-Sender:Resent-To:Resent-Cc:"\
  42. "Resent-Message-ID:In-Reply-To:References:"\
  43. "List-Id:List-Help:List-Unsubscribe:"\
  44. "List-Subscribe:List-Post:List-Owner:List-Archive"
  45. /* -------------------------------------------------------------------------- */
  46. struct pdkim_stringlist {
  47. char *value;
  48. int tag;
  49. void *next;
  50. };
  51. #define PDKIM_STR_ALLOC_FRAG 256
  52. struct pdkim_str {
  53. char *str;
  54. unsigned int len;
  55. unsigned int allocated;
  56. };
  57. /* -------------------------------------------------------------------------- */
  58. /* A bunch of list constants */
  59. const char *pdkim_querymethods[] = {
  60. "dns/txt",
  61. NULL
  62. };
  63. const char *pdkim_algos[] = {
  64. "rsa-sha256",
  65. "rsa-sha1",
  66. NULL
  67. };
  68. const char *pdkim_canons[] = {
  69. "simple",
  70. "relaxed",
  71. NULL
  72. };
  73. const char *pdkim_hashes[] = {
  74. "sha256",
  75. "sha1",
  76. NULL
  77. };
  78. const char *pdkim_keytypes[] = {
  79. "rsa",
  80. NULL
  81. };
  82. typedef struct pdkim_combined_canon_entry {
  83. const char *str;
  84. int canon_headers;
  85. int canon_body;
  86. } pdkim_combined_canon_entry;
  87. pdkim_combined_canon_entry pdkim_combined_canons[] = {
  88. { "simple/simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
  89. { "simple/relaxed", PDKIM_CANON_SIMPLE, PDKIM_CANON_RELAXED },
  90. { "relaxed/simple", PDKIM_CANON_RELAXED, PDKIM_CANON_SIMPLE },
  91. { "relaxed/relaxed", PDKIM_CANON_RELAXED, PDKIM_CANON_RELAXED },
  92. { "simple", PDKIM_CANON_SIMPLE, PDKIM_CANON_SIMPLE },
  93. { "relaxed", PDKIM_CANON_RELAXED, PDKIM_CANON_SIMPLE },
  94. { NULL, 0, 0 }
  95. };
  96. const char *pdkim_verify_status_str(int status) {
  97. switch(status) {
  98. case PDKIM_VERIFY_NONE: return "PDKIM_VERIFY_NONE";
  99. case PDKIM_VERIFY_INVALID: return "PDKIM_VERIFY_INVALID";
  100. case PDKIM_VERIFY_FAIL: return "PDKIM_VERIFY_FAIL";
  101. case PDKIM_VERIFY_PASS: return "PDKIM_VERIFY_PASS";
  102. default: return "PDKIM_VERIFY_UNKNOWN";
  103. }
  104. }
  105. const char *pdkim_verify_ext_status_str(int ext_status) {
  106. switch(ext_status) {
  107. case PDKIM_VERIFY_FAIL_BODY: return "PDKIM_VERIFY_FAIL_BODY";
  108. case PDKIM_VERIFY_FAIL_MESSAGE: return "PDKIM_VERIFY_FAIL_MESSAGE";
  109. case PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE: return "PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE";
  110. case PDKIM_VERIFY_INVALID_BUFFER_SIZE: return "PDKIM_VERIFY_INVALID_BUFFER_SIZE";
  111. case PDKIM_VERIFY_INVALID_PUBKEY_PARSING: return "PDKIM_VERIFY_INVALID_PUBKEY_PARSING";
  112. default: return "PDKIM_VERIFY_UNKNOWN";
  113. }
  114. }
  115. /* -------------------------------------------------------------------------- */
  116. /* Print debugging functions */
  117. #ifdef PDKIM_DEBUG
  118. void pdkim_quoteprint(FILE *stream, const char *data, int len, int lf) {
  119. int i;
  120. const unsigned char *p = (const unsigned char *)data;
  121. for (i=0;i<len;i++) {
  122. const int c = p[i];
  123. switch (c) {
  124. case ' ' : fprintf(stream,"{SP}"); break;
  125. case '\t': fprintf(stream,"{TB}"); break;
  126. case '\r': fprintf(stream,"{CR}"); break;
  127. case '\n': fprintf(stream,"{LF}"); break;
  128. case '{' : fprintf(stream,"{BO}"); break;
  129. case '}' : fprintf(stream,"{BC}"); break;
  130. default:
  131. if ( (c < 32) || (c > 127) )
  132. fprintf(stream,"{%02x}",c);
  133. else
  134. fputc(c,stream);
  135. break;
  136. }
  137. }
  138. if (lf)
  139. fputc('\n',stream);
  140. }
  141. void pdkim_hexprint(FILE *stream, const char *data, int len, int lf) {
  142. int i;
  143. const unsigned char *p = (const unsigned char *)data;
  144. for (i=0;i<len;i++) {
  145. const int c = p[i];
  146. fprintf(stream,"%02x",c);
  147. }
  148. if (lf)
  149. fputc('\n',stream);
  150. }
  151. #endif
  152. /* -------------------------------------------------------------------------- */
  153. /* Simple string list implementation for convinience */
  154. pdkim_stringlist *pdkim_append_stringlist(pdkim_stringlist *base, char *str) {
  155. pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist));
  156. if (new_entry == NULL) return NULL;
  157. memset(new_entry,0,sizeof(pdkim_stringlist));
  158. new_entry->value = strdup(str);
  159. if (new_entry->value == NULL) return NULL;
  160. if (base != NULL) {
  161. pdkim_stringlist *last = base;
  162. while (last->next != NULL) { last = last->next; }
  163. last->next = new_entry;
  164. return base;
  165. }
  166. else return new_entry;
  167. }
  168. pdkim_stringlist *pdkim_prepend_stringlist(pdkim_stringlist *base, char *str) {
  169. pdkim_stringlist *new_entry = malloc(sizeof(pdkim_stringlist));
  170. if (new_entry == NULL) return NULL;
  171. memset(new_entry,0,sizeof(pdkim_stringlist));
  172. new_entry->value = strdup(str);
  173. if (new_entry->value == NULL) return NULL;
  174. if (base != NULL) {
  175. new_entry->next = base;
  176. }
  177. return new_entry;
  178. }
  179. /* -------------------------------------------------------------------------- */
  180. /* A small "growing string" implementation to escape malloc/realloc hell */
  181. pdkim_str *pdkim_strnew (const char *cstr) {
  182. unsigned int len = cstr?strlen(cstr):0;
  183. pdkim_str *p = malloc(sizeof(pdkim_str));
  184. if (p == NULL) return NULL;
  185. memset(p,0,sizeof(pdkim_str));
  186. p->str = malloc(len+1);
  187. if (p->str == NULL) {
  188. free(p);
  189. return NULL;
  190. }
  191. p->allocated=(len+1);
  192. p->len=len;
  193. if (cstr) strcpy(p->str,cstr);
  194. else p->str[p->len] = '\0';
  195. return p;
  196. }
  197. char *pdkim_strncat(pdkim_str *str, const char *data, int len) {
  198. if ((str->allocated - str->len) < (len+1)) {
  199. /* Extend the buffer */
  200. int num_frags = ((len+1)/PDKIM_STR_ALLOC_FRAG)+1;
  201. char *n = realloc(str->str,
  202. (str->allocated+(num_frags*PDKIM_STR_ALLOC_FRAG)));
  203. if (n == NULL) return NULL;
  204. str->str = n;
  205. str->allocated += (num_frags*PDKIM_STR_ALLOC_FRAG);
  206. }
  207. strncpy(&(str->str[str->len]),data,len);
  208. str->len+=len;
  209. str->str[str->len] = '\0';
  210. return str->str;
  211. }
  212. char *pdkim_strcat(pdkim_str *str, const char *cstr) {
  213. return pdkim_strncat(str, cstr, strlen(cstr));
  214. }
  215. char *pdkim_numcat(pdkim_str *str, unsigned long num) {
  216. char minibuf[20];
  217. snprintf(minibuf,20,"%lu",num);
  218. return pdkim_strcat(str,minibuf);
  219. }
  220. char *pdkim_strtrim(pdkim_str *str) {
  221. char *p = str->str;
  222. char *q = str->str;
  223. while ( (*p != '\0') && ((*p == '\t') || (*p == ' ')) ) p++;
  224. while (*p != '\0') {*q = *p; q++; p++;}
  225. *q = '\0';
  226. while ( (q != str->str) && ( (*q == '\0') || (*q == '\t') || (*q == ' ') ) ) {
  227. *q = '\0';
  228. q--;
  229. }
  230. str->len = strlen(str->str);
  231. return str->str;
  232. }
  233. char *pdkim_strclear(pdkim_str *str) {
  234. str->str[0] = '\0';
  235. str->len = 0;
  236. return str->str;
  237. }
  238. void pdkim_strfree(pdkim_str *str) {
  239. if (str == NULL) return;
  240. if (str->str != NULL) free(str->str);
  241. free(str);
  242. }
  243. /* -------------------------------------------------------------------------- */
  244. void pdkim_free_pubkey(pdkim_pubkey *pub) {
  245. if (pub) {
  246. if (pub->version != NULL) free(pub->version);
  247. if (pub->granularity != NULL) free(pub->granularity);
  248. if (pub->hashes != NULL) free(pub->hashes);
  249. if (pub->keytype != NULL) free(pub->keytype);
  250. if (pub->srvtype != NULL) free(pub->srvtype);
  251. if (pub->notes != NULL) free(pub->notes);
  252. if (pub->key != NULL) free(pub->key);
  253. free(pub);
  254. }
  255. }
  256. /* -------------------------------------------------------------------------- */
  257. void pdkim_free_sig(pdkim_signature *sig) {
  258. if (sig) {
  259. pdkim_signature *next = (pdkim_signature *)sig->next;
  260. pdkim_stringlist *e = sig->headers;
  261. while(e != NULL) {
  262. pdkim_stringlist *c = e;
  263. if (e->value != NULL) free(e->value);
  264. e = e->next;
  265. free(c);
  266. }
  267. if (sig->sigdata != NULL) free(sig->sigdata);
  268. if (sig->bodyhash != NULL) free(sig->bodyhash);
  269. if (sig->selector != NULL) free(sig->selector);
  270. if (sig->domain != NULL) free(sig->domain);
  271. if (sig->identity != NULL) free(sig->identity);
  272. if (sig->headernames != NULL) free(sig->headernames);
  273. if (sig->copiedheaders != NULL) free(sig->copiedheaders);
  274. if (sig->rsa_privkey != NULL) free(sig->rsa_privkey);
  275. if (sig->sign_headers != NULL) free(sig->sign_headers);
  276. if (sig->signature_header != NULL) free(sig->signature_header);
  277. if (sig->sha1_body != NULL) free(sig->sha1_body);
  278. if (sig->sha2_body != NULL) free(sig->sha2_body);
  279. if (sig->pubkey != NULL) pdkim_free_pubkey(sig->pubkey);
  280. free(sig);
  281. if (next != NULL) pdkim_free_sig(next);
  282. }
  283. }
  284. /* -------------------------------------------------------------------------- */
  285. DLLEXPORT void pdkim_free_ctx(pdkim_ctx *ctx) {
  286. if (ctx) {
  287. pdkim_stringlist *e = ctx->headers;
  288. while(e != NULL) {
  289. pdkim_stringlist *c = e;
  290. if (e->value != NULL) free(e->value);
  291. e = e->next;
  292. free(c);
  293. }
  294. pdkim_free_sig(ctx->sig);
  295. pdkim_strfree(ctx->cur_header);
  296. free(ctx);
  297. }
  298. }
  299. /* -------------------------------------------------------------------------- */
  300. /* Matches the name of the passed raw "header" against
  301. the passed colon-separated "list", starting at entry
  302. "start". Returns the position of the header name in
  303. the list. */
  304. int header_name_match(const char *header,
  305. char *tick,
  306. int do_tick) {
  307. char *hname;
  308. char *lcopy;
  309. char *p;
  310. char *q;
  311. int rc = PDKIM_FAIL;
  312. /* Get header name */
  313. char *hcolon = strchr(header,':');
  314. if (hcolon == NULL) return rc; /* This isn't a header */
  315. hname = malloc((hcolon-header)+1);
  316. if (hname == NULL) return PDKIM_ERR_OOM;
  317. memset(hname,0,(hcolon-header)+1);
  318. strncpy(hname,header,(hcolon-header));
  319. /* Copy tick-off list locally, so we can punch zeroes into it */
  320. lcopy = strdup(tick);
  321. if (lcopy == NULL) {
  322. free(hname);
  323. return PDKIM_ERR_OOM;
  324. }
  325. p = lcopy;
  326. q = strchr(p,':');
  327. while (q != NULL) {
  328. *q = '\0';
  329. if (strcasecmp(p,hname) == 0) {
  330. rc = PDKIM_OK;
  331. /* Invalidate header name instance in tick-off list */
  332. if (do_tick) tick[p-lcopy] = '_';
  333. goto BAIL;
  334. }
  335. p = q+1;
  336. q = strchr(p,':');
  337. }
  338. if (strcasecmp(p,hname) == 0) {
  339. rc = PDKIM_OK;
  340. /* Invalidate header name instance in tick-off list */
  341. if (do_tick) tick[p-lcopy] = '_';
  342. }
  343. BAIL:
  344. free(hname);
  345. free(lcopy);
  346. return rc;
  347. }
  348. /* -------------------------------------------------------------------------- */
  349. /* Performs "relaxed" canonicalization of a header. The returned pointer needs
  350. to be free()d. */
  351. char *pdkim_relax_header (char *header, int crlf) {
  352. int past_field_name = 0;
  353. int seen_wsp = 0;
  354. char *p = header;
  355. char *q;
  356. char *relaxed = malloc(strlen(header)+3);
  357. if (relaxed == NULL) return NULL;
  358. q = relaxed;
  359. while (*p != '\0') {
  360. int c = *p;
  361. /* Ignore CR & LF */
  362. if ( (c == '\r') || (c == '\n') ) {
  363. p++;
  364. continue;
  365. }
  366. if ( (c == '\t') || (c == ' ') ) {
  367. c = ' '; /* Turns WSP into SP */
  368. if (seen_wsp) {
  369. p++;
  370. continue;
  371. }
  372. else seen_wsp = 1;
  373. }
  374. else {
  375. if ( (!past_field_name) && (c == ':') ) {
  376. if (seen_wsp) q--; /* This removes WSP before the colon */
  377. seen_wsp = 1; /* This removes WSP after the colon */
  378. past_field_name = 1;
  379. }
  380. else seen_wsp = 0;
  381. }
  382. /* Lowercase header name */
  383. if (!past_field_name) c = tolower(c);
  384. *q = c;
  385. p++;
  386. q++;
  387. }
  388. if ((q>relaxed) && (*(q-1) == ' ')) q--; /* Squash eventual trailing SP */
  389. *q = '\0';
  390. if (crlf) strcat(relaxed,"\r\n");
  391. return relaxed;
  392. }
  393. /* -------------------------------------------------------------------------- */
  394. #define PDKIM_QP_ERROR_DECODE -1
  395. char *pdkim_decode_qp_char(char *qp_p, int *c) {
  396. char *initial_pos = qp_p;
  397. /* Advance one char */
  398. qp_p++;
  399. /* Check for two hex digits and decode them */
  400. if (isxdigit(*qp_p) && isxdigit(qp_p[1])) {
  401. /* Do hex conversion */
  402. if (isdigit(*qp_p)) {*c = *qp_p - '0';}
  403. else {*c = toupper(*qp_p) - 'A' + 10;}
  404. *c <<= 4;
  405. if (isdigit(qp_p[1])) {*c |= qp_p[1] - '0';}
  406. else {*c |= toupper(qp_p[1]) - 'A' + 10;}
  407. return qp_p + 2;
  408. }
  409. /* Illegal char here */
  410. *c = PDKIM_QP_ERROR_DECODE;
  411. return initial_pos;
  412. }
  413. /* -------------------------------------------------------------------------- */
  414. char *pdkim_decode_qp(char *str) {
  415. int nchar = 0;
  416. char *q;
  417. char *p = str;
  418. char *n = malloc(strlen(p)+1);
  419. if (n == NULL) return NULL;
  420. *n = '\0';
  421. q = n;
  422. while (*p != '\0') {
  423. if (*p == '=') {
  424. p = pdkim_decode_qp_char(p,&nchar);
  425. if (nchar >= 0) {
  426. *q = nchar;
  427. q++;
  428. continue;
  429. }
  430. }
  431. else {
  432. *q = *p;
  433. q++;
  434. }
  435. p++;
  436. }
  437. *q = '\0';
  438. return n;
  439. }
  440. /* -------------------------------------------------------------------------- */
  441. char *pdkim_decode_base64(char *str, int *num_decoded) {
  442. int dlen = 0;
  443. char *res;
  444. base64_decode(NULL, &dlen, (unsigned char *)str, strlen(str));
  445. res = malloc(dlen+1);
  446. if (res == NULL) return NULL;
  447. if (base64_decode((unsigned char *)res,&dlen,(unsigned char *)str,strlen(str)) != 0) {
  448. free(res);
  449. return NULL;
  450. }
  451. if (num_decoded != NULL) *num_decoded = dlen;
  452. return res;
  453. }
  454. /* -------------------------------------------------------------------------- */
  455. char *pdkim_encode_base64(char *str, int num) {
  456. int dlen = 0;
  457. char *res;
  458. base64_encode(NULL, &dlen, (unsigned char *)str, num);
  459. res = malloc(dlen+1);
  460. if (res == NULL) return NULL;
  461. if (base64_encode((unsigned char *)res,&dlen,(unsigned char *)str,num) != 0) {
  462. free(res);
  463. return NULL;
  464. }
  465. return res;
  466. }
  467. /* -------------------------------------------------------------------------- */
  468. #define PDKIM_HDR_LIMBO 0
  469. #define PDKIM_HDR_TAG 1
  470. #define PDKIM_HDR_VALUE 2
  471. pdkim_signature *pdkim_parse_sig_header(pdkim_ctx *ctx, char *raw_hdr) {
  472. pdkim_signature *sig ;
  473. char *p,*q;
  474. pdkim_str *cur_tag = NULL;
  475. pdkim_str *cur_val = NULL;
  476. int past_hname = 0;
  477. int in_b_val = 0;
  478. int where = PDKIM_HDR_LIMBO;
  479. int i;
  480. sig = malloc(sizeof(pdkim_signature));
  481. if (sig == NULL) return NULL;
  482. memset(sig,0,sizeof(pdkim_signature));
  483. sig->bodylength = -1;
  484. sig->rawsig_no_b_val = malloc(strlen(raw_hdr)+1);
  485. if (sig->rawsig_no_b_val == NULL) {
  486. free(sig);
  487. return NULL;
  488. }
  489. p = raw_hdr;
  490. q = sig->rawsig_no_b_val;
  491. while (1) {
  492. /* Ignore FWS */
  493. if ( (*p == '\r') || (*p == '\n') )
  494. goto NEXT_CHAR;
  495. /* Fast-forward through header name */
  496. if (!past_hname) {
  497. if (*p == ':') past_hname = 1;
  498. goto NEXT_CHAR;
  499. }
  500. if (where == PDKIM_HDR_LIMBO) {
  501. /* In limbo, just wait for a tag-char to appear */
  502. if (!((*p >= 'a') && (*p <= 'z')))
  503. goto NEXT_CHAR;
  504. where = PDKIM_HDR_TAG;
  505. }
  506. if (where == PDKIM_HDR_TAG) {
  507. if (cur_tag == NULL)
  508. cur_tag = pdkim_strnew(NULL);
  509. if ((*p >= 'a') && (*p <= 'z'))
  510. pdkim_strncat(cur_tag,p,1);
  511. if (*p == '=') {
  512. if (strcmp(cur_tag->str,"b") == 0) {
  513. *q = '='; q++;
  514. in_b_val = 1;
  515. }
  516. where = PDKIM_HDR_VALUE;
  517. goto NEXT_CHAR;
  518. }
  519. }
  520. if (where == PDKIM_HDR_VALUE) {
  521. if (cur_val == NULL)
  522. cur_val = pdkim_strnew(NULL);
  523. if ( (*p == '\r') || (*p == '\n') || (*p == ' ') || (*p == '\t') )
  524. goto NEXT_CHAR;
  525. if ( (*p == ';') || (*p == '\0') ) {
  526. if (cur_tag->len > 0) {
  527. pdkim_strtrim(cur_val);
  528. #ifdef PDKIM_DEBUG
  529. if (ctx->debug_stream)
  530. fprintf(ctx->debug_stream, "%s=%s\n", cur_tag->str, cur_val->str);
  531. #endif
  532. switch (cur_tag->str[0]) {
  533. case 'b':
  534. switch (cur_tag->str[1]) {
  535. case 'h':
  536. sig->bodyhash = pdkim_decode_base64(cur_val->str,&(sig->bodyhash_len));
  537. break;
  538. default:
  539. sig->sigdata = pdkim_decode_base64(cur_val->str,&(sig->sigdata_len));
  540. break;
  541. }
  542. break;
  543. case 'v':
  544. if (strcmp(cur_val->str,PDKIM_SIGNATURE_VERSION) == 0) {
  545. /* We only support version 1, and that is currently the
  546. only version there is. */
  547. sig->version = 1;
  548. }
  549. break;
  550. case 'a':
  551. i = 0;
  552. while (pdkim_algos[i] != NULL) {
  553. if (strcmp(cur_val->str,pdkim_algos[i]) == 0 ) {
  554. sig->algo = i;
  555. break;
  556. }
  557. i++;
  558. }
  559. break;
  560. case 'c':
  561. i = 0;
  562. while (pdkim_combined_canons[i].str != NULL) {
  563. if (strcmp(cur_val->str,pdkim_combined_canons[i].str) == 0 ) {
  564. sig->canon_headers = pdkim_combined_canons[i].canon_headers;
  565. sig->canon_body = pdkim_combined_canons[i].canon_body;
  566. break;
  567. }
  568. i++;
  569. }
  570. break;
  571. case 'q':
  572. i = 0;
  573. while (pdkim_querymethods[i] != NULL) {
  574. if (strcmp(cur_val->str,pdkim_querymethods[i]) == 0 ) {
  575. sig->querymethod = i;
  576. break;
  577. }
  578. i++;
  579. }
  580. break;
  581. case 's':
  582. sig->selector = strdup(cur_val->str);
  583. break;
  584. case 'd':
  585. sig->domain = strdup(cur_val->str);
  586. break;
  587. case 'i':
  588. sig->identity = pdkim_decode_qp(cur_val->str);
  589. break;
  590. case 't':
  591. sig->created = strtoul(cur_val->str,NULL,10);
  592. break;
  593. case 'x':
  594. sig->expires = strtoul(cur_val->str,NULL,10);
  595. break;
  596. case 'l':
  597. sig->bodylength = strtol(cur_val->str,NULL,10);
  598. break;
  599. case 'h':
  600. sig->headernames = strdup(cur_val->str);
  601. break;
  602. case 'z':
  603. sig->copiedheaders = pdkim_decode_qp(cur_val->str);
  604. break;
  605. default:
  606. #ifdef PDKIM_DEBUG
  607. if (ctx->debug_stream)
  608. fprintf(ctx->debug_stream, "Unknown tag encountered\n");
  609. #endif
  610. break;
  611. }
  612. }
  613. pdkim_strclear(cur_tag);
  614. pdkim_strclear(cur_val);
  615. in_b_val = 0;
  616. where = PDKIM_HDR_LIMBO;
  617. goto NEXT_CHAR;
  618. }
  619. else pdkim_strncat(cur_val,p,1);
  620. }
  621. NEXT_CHAR:
  622. if (*p == '\0') break;
  623. if (!in_b_val) {
  624. *q = *p;
  625. q++;
  626. }
  627. p++;
  628. }
  629. /* Make sure the most important bits are there. */
  630. if (!(sig->domain && (*(sig->domain) != '\0') &&
  631. sig->selector && (*(sig->selector) != '\0') &&
  632. sig->headernames && (*(sig->headernames) != '\0') &&
  633. sig->bodyhash &&
  634. sig->sigdata &&
  635. sig->version)) {
  636. pdkim_free_sig(sig);
  637. return NULL;
  638. }
  639. *q = '\0';
  640. /* Chomp raw header. The final newline must not be added to the signature. */
  641. q--;
  642. while( (q > sig->rawsig_no_b_val) && ((*q == '\r') || (*q == '\n')) ) {
  643. *q = '\0'; q--;
  644. }
  645. #ifdef PDKIM_DEBUG
  646. if (ctx->debug_stream) {
  647. fprintf(ctx->debug_stream,
  648. "PDKIM >> Raw signature w/o b= tag value >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
  649. pdkim_quoteprint(ctx->debug_stream,
  650. sig->rawsig_no_b_val,
  651. strlen(sig->rawsig_no_b_val), 1);
  652. fprintf(ctx->debug_stream,
  653. "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
  654. }
  655. #endif
  656. sig->sha1_body = malloc(sizeof(sha1_context));
  657. if (sig->sha1_body == NULL) {
  658. pdkim_free_sig(sig);
  659. return NULL;
  660. }
  661. sig->sha2_body = malloc(sizeof(sha2_context));
  662. if (sig->sha2_body == NULL) {
  663. pdkim_free_sig(sig);
  664. return NULL;
  665. }
  666. sha1_starts(sig->sha1_body);
  667. sha2_starts(sig->sha2_body,0);
  668. return sig;
  669. }
  670. /* -------------------------------------------------------------------------- */
  671. pdkim_pubkey *pdkim_parse_pubkey_record(pdkim_ctx *ctx, char *raw_record) {
  672. pdkim_pubkey *pub ;
  673. char *p;
  674. pdkim_str *cur_tag = NULL;
  675. pdkim_str *cur_val = NULL;
  676. int where = PDKIM_HDR_LIMBO;
  677. pub = malloc(sizeof(pdkim_pubkey));
  678. if (pub == NULL) return NULL;
  679. memset(pub,0,sizeof(pdkim_pubkey));
  680. p = raw_record;
  681. while (1) {
  682. /* Ignore FWS */
  683. if ( (*p == '\r') || (*p == '\n') )
  684. goto NEXT_CHAR;
  685. if (where == PDKIM_HDR_LIMBO) {
  686. /* In limbo, just wait for a tag-char to appear */
  687. if (!((*p >= 'a') && (*p <= 'z')))
  688. goto NEXT_CHAR;
  689. where = PDKIM_HDR_TAG;
  690. }
  691. if (where == PDKIM_HDR_TAG) {
  692. if (cur_tag == NULL)
  693. cur_tag = pdkim_strnew(NULL);
  694. if ((*p >= 'a') && (*p <= 'z'))
  695. pdkim_strncat(cur_tag,p,1);
  696. if (*p == '=') {
  697. where = PDKIM_HDR_VALUE;
  698. goto NEXT_CHAR;
  699. }
  700. }
  701. if (where == PDKIM_HDR_VALUE) {
  702. if (cur_val == NULL)
  703. cur_val = pdkim_strnew(NULL);
  704. if ( (*p == '\r') || (*p == '\n') )
  705. goto NEXT_CHAR;
  706. if ( (*p == ';') || (*p == '\0') ) {
  707. if (cur_tag->len > 0) {
  708. pdkim_strtrim(cur_val);
  709. #ifdef PDKIM_DEBUG
  710. if (ctx->debug_stream)
  711. fprintf(ctx->debug_stream, "%s=%s\n", cur_tag->str, cur_val->str);
  712. #endif
  713. switch (cur_tag->str[0]) {
  714. case 'v':
  715. /* This tag isn't evaluated because:
  716. - We only support version DKIM1.
  717. - Which is the default for this value (set below)
  718. - Other versions are currently not specified. */
  719. break;
  720. case 'h':
  721. pub->hashes = strdup(cur_val->str);
  722. break;
  723. case 'g':
  724. pub->granularity = strdup(cur_val->str);
  725. break;
  726. case 'n':
  727. pub->notes = pdkim_decode_qp(cur_val->str);
  728. break;
  729. case 'p':
  730. pub->key = pdkim_decode_base64(cur_val->str,&(pub->key_len));
  731. break;
  732. case 'k':
  733. pub->hashes = strdup(cur_val->str);
  734. break;
  735. case 's':
  736. pub->srvtype = strdup(cur_val->str);
  737. break;
  738. case 't':
  739. if (strchr(cur_val->str,'y') != NULL) pub->testing = 1;
  740. if (strchr(cur_val->str,'s') != NULL) pub->no_subdomaining = 1;
  741. break;
  742. default:
  743. #ifdef PDKIM_DEBUG
  744. if (ctx->debug_stream)
  745. fprintf(ctx->debug_stream, "Unknown tag encountered\n");
  746. #endif
  747. break;
  748. }
  749. }
  750. pdkim_strclear(cur_tag);
  751. pdkim_strclear(cur_val);
  752. where = PDKIM_HDR_LIMBO;
  753. goto NEXT_CHAR;
  754. }
  755. else pdkim_strncat(cur_val,p,1);
  756. }
  757. NEXT_CHAR:
  758. if (*p == '\0') break;
  759. p++;
  760. }
  761. /* Set fallback defaults */
  762. if (pub->version == NULL) pub->version = strdup(PDKIM_PUB_RECORD_VERSION);
  763. if (pub->granularity == NULL) pub->granularity = strdup("*");
  764. if (pub->keytype == NULL) pub->keytype = strdup("rsa");
  765. if (pub->srvtype == NULL) pub->srvtype = strdup("*");
  766. /* p= is required */
  767. if (pub->key == NULL) {
  768. pdkim_free_pubkey(pub);
  769. return NULL;
  770. }
  771. return pub;
  772. }
  773. /* -------------------------------------------------------------------------- */
  774. int pdkim_update_bodyhash(pdkim_ctx *ctx, const char *data, int len) {
  775. pdkim_signature *sig = ctx->sig;
  776. /* Cache relaxed version of data */
  777. char *relaxed_data = NULL;
  778. int relaxed_len = 0;
  779. /* Traverse all signatures, updating their hashes. */
  780. while (sig != NULL) {
  781. /* Defaults to simple canon (no further treatment necessary) */
  782. const char *canon_data = data;
  783. int canon_len = len;
  784. if (sig->canon_body == PDKIM_CANON_RELAXED) {
  785. /* Relax the line if not done already */
  786. if (relaxed_data == NULL) {
  787. int seen_wsp = 0;
  788. const char *p = data;
  789. int q = 0;
  790. relaxed_data = malloc(len+1);
  791. if (relaxed_data == NULL) return PDKIM_ERR_OOM;
  792. while (*p != '\0') {
  793. char c = *p;
  794. if (c == '\r') {
  795. if ( (q > 0) && (relaxed_data[q-1] == ' ') ) q--;
  796. }
  797. else if ( (c == '\t') || (c == ' ') ) {
  798. c = ' '; /* Turns WSP into SP */
  799. if (seen_wsp) {
  800. p++;
  801. continue;
  802. }
  803. else seen_wsp = 1;
  804. }
  805. else seen_wsp = 0;
  806. relaxed_data[q++] = c;
  807. p++;
  808. }
  809. relaxed_data[q] = '\0';
  810. relaxed_len = q;
  811. }
  812. canon_data = relaxed_data;
  813. canon_len = relaxed_len;
  814. }
  815. /* Make sure we don't exceed the to-be-signed body length */
  816. if ((sig->bodylength >= 0) &&
  817. ((sig->signed_body_bytes+(unsigned long)canon_len) > sig->bodylength))
  818. canon_len = (sig->bodylength - sig->signed_body_bytes);
  819. if (canon_len > 0) {
  820. if (sig->algo == PDKIM_ALGO_RSA_SHA1)
  821. sha1_update(sig->sha1_body,(unsigned char *)canon_data,canon_len);
  822. else
  823. sha2_update(sig->sha2_body,(unsigned char *)canon_data,canon_len);
  824. sig->signed_body_bytes += canon_len;
  825. #ifdef PDKIM_DEBUG
  826. if (ctx->debug_stream!=NULL)
  827. pdkim_quoteprint(ctx->debug_stream,canon_data,canon_len,0);
  828. #endif
  829. }
  830. sig = sig->next;
  831. }
  832. if (relaxed_data != NULL) free(relaxed_data);
  833. return PDKIM_OK;
  834. }
  835. /* -------------------------------------------------------------------------- */
  836. int pdkim_finish_bodyhash(pdkim_ctx *ctx) {
  837. pdkim_signature *sig = ctx->sig;
  838. /* Traverse all signatures */
  839. while (sig != NULL) {
  840. /* Finish hashes */
  841. unsigned char bh[32]; /* SHA-256 = 32 Bytes, SHA-1 = 20 Bytes */
  842. if (sig->algo == PDKIM_ALGO_RSA_SHA1)
  843. sha1_finish(sig->sha1_body,bh);
  844. else
  845. sha2_finish(sig->sha2_body,bh);
  846. #ifdef PDKIM_DEBUG
  847. if (ctx->debug_stream) {
  848. fprintf(ctx->debug_stream, "PDKIM [%s] Body bytes hashed: %lu\n",
  849. sig->domain, sig->signed_body_bytes);
  850. fprintf(ctx->debug_stream, "PDKIM [%s] bh computed: ", sig->domain);
  851. pdkim_hexprint(ctx->debug_stream, (char *)bh,
  852. (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32,1);
  853. }
  854. #endif
  855. /* SIGNING -------------------------------------------------------------- */
  856. if (ctx->mode == PDKIM_MODE_SIGN) {
  857. sig->bodyhash_len = (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32;
  858. sig->bodyhash = malloc(sig->bodyhash_len);
  859. if (sig->bodyhash == NULL) return PDKIM_ERR_OOM;
  860. memcpy(sig->bodyhash,bh,sig->bodyhash_len);
  861. /* If bodylength limit is set, and we have received less bytes
  862. than the requested amount, effectively remove the limit tag. */
  863. if (sig->signed_body_bytes < sig->bodylength) sig->bodylength = -1;
  864. }
  865. /* VERIFICATION --------------------------------------------------------- */
  866. else {
  867. /* Compare bodyhash */
  868. if (memcmp(bh,sig->bodyhash,
  869. (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32) == 0) {
  870. #ifdef PDKIM_DEBUG
  871. if (ctx->debug_stream)
  872. fprintf(ctx->debug_stream, "PDKIM [%s] Body hash verified OK\n",
  873. sig->domain);
  874. #endif
  875. }
  876. else {
  877. #ifdef PDKIM_DEBUG
  878. if (ctx->debug_stream) {
  879. fprintf(ctx->debug_stream, "PDKIM [%s] Body hash did NOT verify\n",
  880. sig->domain);
  881. fprintf(ctx->debug_stream, "PDKIM [%s] bh signature: ", sig->domain);
  882. pdkim_hexprint(ctx->debug_stream, sig->bodyhash,
  883. (sig->algo == PDKIM_ALGO_RSA_SHA1)?20:32,1);
  884. }
  885. #endif
  886. sig->verify_status = PDKIM_VERIFY_FAIL;
  887. sig->verify_ext_status = PDKIM_VERIFY_FAIL_BODY;
  888. }
  889. }
  890. sig = sig->next;
  891. }
  892. return PDKIM_OK;
  893. }
  894. /* -------------------------------------------------------------------------- */
  895. /* Callback from pdkim_feed below for processing complete body lines */
  896. int pdkim_bodyline_complete(pdkim_ctx *ctx) {
  897. char *p = ctx->linebuf;
  898. int n = ctx->linebuf_offset;
  899. /* Ignore extra data if we've seen the end-of-data marker */
  900. if (ctx->seen_eod) goto BAIL;
  901. /* We've always got one extra byte to stuff a zero ... */
  902. ctx->linebuf[(ctx->linebuf_offset)] = '\0';
  903. if (ctx->input_mode == PDKIM_INPUT_SMTP) {
  904. /* Terminate on EOD marker */
  905. if (memcmp(p,".\r\n",3) == 0) {
  906. ctx->seen_eod = 1;
  907. goto BAIL;
  908. }
  909. /* Unstuff dots */
  910. if (memcmp(p,"..",2) == 0) {
  911. p++;
  912. n--;
  913. }
  914. }
  915. /* Empty lines need to be buffered until we find a non-empty line */
  916. if (memcmp(p,"\r\n",2) == 0) {
  917. ctx->num_buffered_crlf++;
  918. goto BAIL;
  919. }
  920. /* At this point, we have a non-empty line, so release the buffered ones. */
  921. while (ctx->num_buffered_crlf) {
  922. pdkim_update_bodyhash(ctx,"\r\n",2);
  923. ctx->num_buffered_crlf--;
  924. }
  925. pdkim_update_bodyhash(ctx,p,n);
  926. BAIL:
  927. ctx->linebuf_offset = 0;
  928. return PDKIM_OK;
  929. }
  930. /* -------------------------------------------------------------------------- */
  931. /* Callback from pdkim_feed below for processing complete headers */
  932. #define DKIM_SIGNATURE_HEADERNAME "DKIM-Signature:"
  933. int pdkim_header_complete(pdkim_ctx *ctx) {
  934. pdkim_signature *sig = ctx->sig;
  935. /* Special case: The last header can have an extra \r appended */
  936. if ( (ctx->cur_header->len > 1) &&
  937. (ctx->cur_header->str[(ctx->cur_header->len)-1] == '\r') ) {
  938. ctx->cur_header->str[(ctx->cur_header->len)-1] = '\0';
  939. ctx->cur_header->len--;
  940. }
  941. ctx->num_headers++;
  942. if (ctx->num_headers > PDKIM_MAX_HEADERS) goto BAIL;
  943. /* SIGNING -------------------------------------------------------------- */
  944. if (ctx->mode == PDKIM_MODE_SIGN) {
  945. /* Traverse all signatures */
  946. while (sig != NULL) {
  947. pdkim_stringlist *list;
  948. if (header_name_match(ctx->cur_header->str,
  949. sig->sign_headers?
  950. sig->sign_headers:
  951. PDKIM_DEFAULT_SIGN_HEADERS, 0) != PDKIM_OK) goto NEXT_SIG;
  952. /* Add header to the signed headers list (in reverse order) */
  953. list = pdkim_prepend_stringlist(sig->headers,
  954. ctx->cur_header->str);
  955. if (list == NULL) return PDKIM_ERR_OOM;
  956. sig->headers = list;
  957. NEXT_SIG:
  958. sig = sig->next;
  959. }
  960. }
  961. /* DKIM-Signature: headers are added to the verification list */
  962. if (ctx->mode == PDKIM_MODE_VERIFY) {
  963. if (strncasecmp(ctx->cur_header->str,
  964. DKIM_SIGNATURE_HEADERNAME,
  965. strlen(DKIM_SIGNATURE_HEADERNAME)) == 0) {
  966. pdkim_signature *new_sig;
  967. /* Create and chain new signature block */
  968. #ifdef PDKIM_DEBUG
  969. if (ctx->debug_stream)
  970. fprintf(ctx->debug_stream,
  971. "PDKIM >> Found sig, trying to parse >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
  972. #endif
  973. new_sig = pdkim_parse_sig_header(ctx, ctx->cur_header->str);
  974. if (new_sig != NULL) {
  975. pdkim_signature *last_sig = ctx->sig;
  976. if (last_sig == NULL) {
  977. ctx->sig = new_sig;
  978. }
  979. else {
  980. while (last_sig->next != NULL) { last_sig = last_sig->next; }
  981. last_sig->next = new_sig;
  982. }
  983. }
  984. else {
  985. #ifdef PDKIM_DEBUG
  986. if (ctx->debug_stream) {
  987. fprintf(ctx->debug_stream,"Error while parsing signature header\n");
  988. fprintf(ctx->debug_stream,
  989. "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
  990. }
  991. #endif
  992. }
  993. }
  994. /* every other header is stored for signature verification */
  995. else {
  996. pdkim_stringlist *list;
  997. list = pdkim_prepend_stringlist(ctx->headers,
  998. ctx->cur_header->str);
  999. if (list == NULL) return PDKIM_ERR_OOM;
  1000. ctx->headers = list;
  1001. }
  1002. }
  1003. BAIL:
  1004. pdkim_strclear(ctx->cur_header); /* Re-use existing pdkim_str */
  1005. return PDKIM_OK;
  1006. }
  1007. /* -------------------------------------------------------------------------- */
  1008. #define HEADER_BUFFER_FRAG_SIZE 256
  1009. DLLEXPORT int pdkim_feed (pdkim_ctx *ctx,
  1010. char *data,
  1011. int len) {
  1012. int p;
  1013. for (p=0;p<len;p++) {
  1014. char c = data[p];
  1015. if (ctx->past_headers) {
  1016. /* Processing body byte */
  1017. ctx->linebuf[(ctx->linebuf_offset)++] = c;
  1018. if (c == '\n') {
  1019. int rc = pdkim_bodyline_complete(ctx); /* End of line */
  1020. if (rc != PDKIM_OK) return rc;
  1021. }
  1022. if (ctx->linebuf_offset == (PDKIM_MAX_BODY_LINE_LEN-1))
  1023. return PDKIM_ERR_LONG_LINE;
  1024. }
  1025. else {
  1026. /* Processing header byte */
  1027. if (c != '\r') {
  1028. if (c == '\n') {
  1029. if (ctx->seen_lf) {
  1030. int rc = pdkim_header_complete(ctx); /* Seen last header line */
  1031. if (rc != PDKIM_OK) return rc;
  1032. ctx->past_headers = 1;
  1033. ctx->seen_lf = 0;
  1034. #ifdef PDKIM_DEBUG
  1035. if (ctx->debug_stream)
  1036. fprintf(ctx->debug_stream,
  1037. "PDKIM >> Hashed body data, canonicalized >>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
  1038. #endif
  1039. continue;
  1040. }
  1041. else ctx->seen_lf = 1;
  1042. }
  1043. else if (ctx->seen_lf) {
  1044. if (! ((c == '\t') || (c == ' '))) {
  1045. int rc = pdkim_header_complete(ctx); /* End of header */
  1046. if (rc != PDKIM_OK) return rc;
  1047. }
  1048. ctx->seen_lf = 0;
  1049. }
  1050. }
  1051. if (ctx->cur_header == NULL) {
  1052. ctx->cur_header = pdkim_strnew(NULL);
  1053. if (ctx->cur_header == NULL) return PDKIM_ERR_OOM;
  1054. }
  1055. if (ctx->cur_header->len < PDKIM_MAX_HEADER_LEN)
  1056. if (pdkim_strncat(ctx->cur_header,&data[p],1) == NULL)
  1057. return PDKIM_ERR_OOM;
  1058. }
  1059. }
  1060. return PDKIM_OK;
  1061. }
  1062. /*
  1063. * RFC 5322 specifies that header line length SHOULD be no more than 78
  1064. * lets make it so!
  1065. * pdkim_headcat
  1066. * returns char*
  1067. *
  1068. * col: this int holds and receives column number (octets since last '\n')
  1069. * str: partial string to append to
  1070. * pad: padding, split line or space after before or after eg: ";"
  1071. * intro: - must join to payload eg "h=", usually the tag name
  1072. * payload: eg base64 data - long data can be split arbitrarily.
  1073. *
  1074. * this code doesn't fold the header in some of the places that RFC4871
  1075. * allows: As per RFC5322(2.2.3) it only folds before or after tag-value
  1076. * pairs and inside long values. it also always spaces or breaks after the
  1077. * "pad"
  1078. *
  1079. * no guarantees are made for output given out-of range input. like tag
  1080. * names loinger than 78, or bogus col. Input is assumed to be free of line breaks.
  1081. */
  1082. static char *pdkim_headcat(int *col, pdkim_str *str, const char*pad,const char *intro, const char *payload ) {
  1083. size_t l;
  1084. if( pad)
  1085. {
  1086. l = strlen(pad);
  1087. if( *col + l > 78 )
  1088. {
  1089. pdkim_strcat(str, "\r\n\t");
  1090. *col=1;
  1091. }
  1092. pdkim_strncat(str, pad,l);
  1093. *col +=l;
  1094. }
  1095. l=(pad?1:0) + (intro?strlen(intro):0 );
  1096. if( *col + l > 78 )
  1097. { /*can't fit intro - start a new line to make room.*/
  1098. pdkim_strcat(str, "\r\n\t");
  1099. *col=1;
  1100. l= intro?strlen(intro):0;
  1101. }
  1102. l += payload ? strlen(payload):0 ;
  1103. while(l>77)
  1104. { /* this fragment will not fit on a single line */
  1105. if( pad )
  1106. {
  1107. pdkim_strcat(str, " ");
  1108. *col +=1;
  1109. pad=NULL; // only want this once
  1110. l--;
  1111. }
  1112. if( intro )
  1113. {
  1114. size_t sl=strlen(intro);
  1115. pdkim_strncat(str, intro,sl);
  1116. *col +=sl;
  1117. l-=sl;
  1118. intro=NULL; // only want this once
  1119. }
  1120. if(payload)
  1121. {
  1122. size_t sl=strlen(payload);
  1123. size_t chomp = *col+sl < 77 ? sl : 78-*col;
  1124. pdkim_strncat(str, payload,chomp);
  1125. *col +=chomp;
  1126. payload+=chomp;
  1127. l-=chomp-1;
  1128. }
  1129. // the while precondition tells us it didn't fit.
  1130. pdkim_strcat(str, "\r\n\t");
  1131. *col=1;
  1132. }
  1133. if( *col + l > 78 )
  1134. {
  1135. pdkim_strcat(str, "\r\n\t");
  1136. *col=1;
  1137. pad=NULL;
  1138. }
  1139. if( pad )
  1140. {
  1141. pdkim_strcat(str, " ");
  1142. *col +=1;
  1143. pad=NULL;
  1144. }
  1145. if( intro )
  1146. {
  1147. size_t sl=strlen(intro);
  1148. pdkim_strncat(str, intro,sl);
  1149. *col +=sl;
  1150. l-=sl;
  1151. intro=NULL;
  1152. }
  1153. if(payload)
  1154. {
  1155. size_t sl=strlen(payload);
  1156. pdkim_strncat(str, payload,sl);
  1157. *col +=sl;
  1158. }
  1159. return str->str;
  1160. }
  1161. /* -------------------------------------------------------------------------- */
  1162. char *pdkim_create_header(pdkim_signature *sig, int final) {
  1163. char *rc = NULL;
  1164. char *base64_bh = NULL;
  1165. char *base64_b = NULL;
  1166. int col=0;
  1167. pdkim_str *hdr = pdkim_strnew("DKIM-Signature: v="PDKIM_SIGNATURE_VERSION);
  1168. if (hdr == NULL) return NULL;
  1169. pdkim_str *canon_all = pdkim_strnew(pdkim_canons[sig->canon_headers]);
  1170. if (canon_all == NULL) goto BAIL;
  1171. base64_bh = pdkim_encode_base64(sig->bodyhash, sig->bodyhash_len);
  1172. if (base64_bh == NULL) goto BAIL;
  1173. col=strlen(hdr->str);
  1174. /* Required and static bits */
  1175. if (
  1176. pdkim_headcat(&col,hdr,";","a=",pdkim_algos[sig->algo]) &&
  1177. pdkim_headcat(&col,hdr,";","q=",pdkim_querymethods[sig->querymethod]) &&
  1178. pdkim_strcat(canon_all,"/") &&
  1179. pdkim_strcat(canon_all,pdkim_canons[sig->canon_body]) &&
  1180. pdkim_headcat(&col,hdr,";","c=",canon_all->str) &&
  1181. pdkim_headcat(&col,hdr,";","d=",sig->domain) &&
  1182. pdkim_headcat(&col,hdr,";","s=",sig->selector)
  1183. ) {
  1184. /* list of eader names can be split between items. */
  1185. {
  1186. char *n=strdup(sig->headernames);
  1187. char *f=n;
  1188. char *i="h=";
  1189. char *s=";";
  1190. if(!n) goto BAIL;
  1191. while (*n)
  1192. {
  1193. char *c=strchr(n,':');
  1194. if(c) *c='\0';
  1195. if(!i)
  1196. {
  1197. if (!pdkim_headcat(&col,hdr,NULL,NULL,":"))
  1198. {
  1199. free(f);
  1200. goto BAIL;
  1201. }
  1202. }
  1203. if( !pdkim_headcat(&col,hdr,s,i,n))
  1204. {
  1205. free(f);
  1206. goto BAIL;
  1207. }
  1208. if(c) n=c+1 ; else break;
  1209. s=NULL;
  1210. i=NULL;
  1211. }
  1212. free(f);
  1213. }
  1214. if(!pdkim_headcat(&col,hdr,";","bh=",base64_bh))
  1215. goto BAIL;
  1216. /* Optional bits */
  1217. if (sig->identity != NULL) {
  1218. if(!pdkim_headcat(&col,hdr,";","i=",sig->identity)){
  1219. goto BAIL;
  1220. }
  1221. }
  1222. if (sig->created > 0) {
  1223. char minibuf[20];
  1224. snprintf(minibuf,20,"%lu",sig->created);
  1225. if(!pdkim_headcat(&col,hdr,";","t=",minibuf)) {
  1226. goto BAIL;
  1227. }
  1228. }
  1229. if (sig->expires > 0) {
  1230. char minibuf[20];
  1231. snprintf(minibuf,20,"%lu",sig->expires);
  1232. if(!pdkim_headcat(&col,hdr,";","x=",minibuf)) {
  1233. goto BAIL;
  1234. }
  1235. }
  1236. if (sig->bodylength >= 0) {
  1237. char minibuf[20];
  1238. snprintf(minibuf,20,"%lu",sig->bodylength);
  1239. if(!pdkim_headcat(&col,hdr,";","l=",minibuf)) {
  1240. goto BAIL;
  1241. }
  1242. }
  1243. /* Preliminary or final version? */
  1244. if (final) {
  1245. base64_b = pdkim_encode_base64(sig->sigdata, sig->sigdata_len);
  1246. if (base64_b == NULL) goto BAIL;
  1247. if(!pdkim_headcat(&col,hdr,";","b=",base64_b)) goto BAIL;
  1248. }
  1249. else {
  1250. if(!pdkim_headcat(&col,hdr,";","b=","")) goto BAIL;
  1251. }
  1252. /* add trailing semicolon: I'm not sure if this is actually needed */
  1253. if(!pdkim_headcat(&col,hdr,NULL,";","")) goto BAIL;
  1254. goto DONE;
  1255. }
  1256. DONE:
  1257. rc = strdup(hdr->str);
  1258. BAIL:
  1259. pdkim_strfree(hdr);
  1260. if (canon_all != NULL) pdkim_strfree(canon_all);
  1261. if (base64_bh != NULL) free(base64_bh);
  1262. if (base64_b != NULL) free(base64_b);
  1263. return rc;
  1264. }
  1265. /* -------------------------------------------------------------------------- */
  1266. DLLEXPORT int pdkim_feed_finish(pdkim_ctx *ctx, pdkim_signature **return_signatures) {
  1267. pdkim_signature *sig = ctx->sig;
  1268. pdkim_str *headernames = NULL; /* Collected signed header names */
  1269. /* Check if we must still flush a (partial) header. If that is the
  1270. case, the message has no body, and we must compute a body hash
  1271. out of '<CR><LF>' */
  1272. if (ctx->cur_header && ctx->cur_header->len) {
  1273. int rc = pdkim_header_complete(ctx);
  1274. if (rc != PDKIM_OK) return rc;
  1275. pdkim_update_bodyhash(ctx,"\r\n",2);
  1276. }
  1277. else {
  1278. /* For non-smtp input, check if there's an unfinished line in the
  1279. body line buffer. If that is the case, we must add a CRLF to the
  1280. hash to properly terminate the message. */
  1281. if ((ctx->input_mode == PDKIM_INPUT_NORMAL) && ctx->linebuf_offset) {
  1282. pdkim_update_bodyhash(ctx, ctx->linebuf, ctx->linebuf_offset);
  1283. pdkim_update_bodyhash(ctx,"\r\n",2);
  1284. }
  1285. #ifdef PDKIM_DEBUG
  1286. if (ctx->debug_stream)
  1287. fprintf(ctx->debug_stream,
  1288. "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
  1289. #endif
  1290. }
  1291. /* Build (and/or evaluate) body hash */
  1292. if (pdkim_finish_bodyhash(ctx) != PDKIM_OK) return PDKIM_ERR_OOM;
  1293. /* SIGNING -------------------------------------------------------------- */
  1294. if (ctx->mode == PDKIM_MODE_SIGN) {
  1295. headernames = pdkim_strnew(NULL);
  1296. if (headernames == NULL) return PDKIM_ERR_OOM;
  1297. }
  1298. /* ---------------------------------------------------------------------- */
  1299. while (sig != NULL) {
  1300. sha1_context sha1_headers;
  1301. sha2_context sha2_headers;
  1302. char *sig_hdr;
  1303. char headerhash[32];
  1304. if (sig->algo == PDKIM_ALGO_RSA_SHA1)
  1305. sha1_starts(&sha1_headers);
  1306. else
  1307. sha2_starts(&sha2_headers,0);
  1308. #ifdef PDKIM_DEBUG
  1309. if (ctx->debug_stream)
  1310. fprintf(ctx->debug_stream,
  1311. "PDKIM >> Hashed header data, canonicalized, in sequence >>>>>>>>>>>>>>\n");
  1312. #endif
  1313. /* SIGNING ---------------------------------------------------------------- */
  1314. /* When signing, walk through our header list and add them to the hash. As we
  1315. go, construct a list of the header's names to use for the h= parameter. */
  1316. if (ctx->mode == PDKIM_MODE_SIGN) {
  1317. pdkim_stringlist *p = sig->headers;
  1318. while (p != NULL) {
  1319. char *rh = NULL;
  1320. /* Collect header names (Note: colon presence is guaranteed here) */
  1321. char *q = strchr(p->value,':');
  1322. if (pdkim_strncat(headernames, p->value,
  1323. (q-(p->value))+((p->next==NULL)?0:1)) == NULL)
  1324. return PDKIM_ERR_OOM;
  1325. if (sig->canon_headers == PDKIM_CANON_RELAXED)
  1326. rh = pdkim_relax_header(p->value,1); /* cook header for relaxed canon */
  1327. else
  1328. rh = strdup(p->value); /* just copy it for simple canon */
  1329. if (rh == NULL) return PDKIM_ERR_OOM;
  1330. /* Feed header to the hash algorithm */
  1331. if (sig->algo == PDKIM_ALGO_RSA_SHA1)
  1332. sha1_update(&(sha1_headers),(unsigned char *)rh,strlen(rh));
  1333. else
  1334. sha2_update(&(sha2_headers),(unsigned char *)rh,strlen(rh));
  1335. #ifdef PDKIM_DEBUG
  1336. if (ctx->debug_stream)
  1337. pdkim_quoteprint(ctx->debug_stream, rh, strlen(rh), 1);
  1338. #endif
  1339. free(rh);
  1340. p = p->next;
  1341. }
  1342. }
  1343. /* VERIFICATION ----------------------------------------------------------- */
  1344. /* When verifying, walk through the header name list in the h= parameter and
  1345. add the headers to the hash in that order. */
  1346. else {
  1347. char *b = strdup(sig->headernames);
  1348. char *p = b;
  1349. char *q = NULL;
  1350. pdkim_stringlist *hdrs = ctx->headers;
  1351. if (b == NULL) return PDKIM_ERR_OOM;
  1352. /* clear tags */
  1353. while (hdrs != NULL) {
  1354. hdrs->tag = 0;
  1355. hdrs = hdrs->next;
  1356. }
  1357. while(1) {
  1358. hdrs = ctx->headers;
  1359. q = strchr(p,':');
  1360. if (q != NULL) *q = '\0';
  1361. while (hdrs != NULL) {
  1362. if ( (hdrs->tag == 0) &&
  1363. (strncasecmp(hdrs->value,p,strlen(p)) == 0) &&
  1364. ((hdrs->value)[strlen(p)] == ':') ) {
  1365. char *rh = NULL;
  1366. if (sig->canon_headers == PDKIM_CANON_RELAXED)
  1367. rh = pdkim_relax_header(hdrs->value,1); /* cook header for relaxed canon */
  1368. else
  1369. rh = strdup(hdrs->value); /* just copy it for simple canon */
  1370. if (rh == NULL) return PDKIM_ERR_OOM;
  1371. /* Feed header to the hash algorithm */
  1372. if (sig->algo == PDKIM_ALGO_RSA_SHA1)
  1373. sha1_update(&(sha1_headers),(unsigned char *)rh,strlen(rh));
  1374. else
  1375. sha2_update(&(sha2_headers),(unsigned char *)rh,strlen(rh));
  1376. #ifdef PDKIM_DEBUG
  1377. if (ctx->debug_stream)
  1378. pdkim_quoteprint(ctx->debug_stream, rh, strlen(rh), 1);
  1379. #endif
  1380. free(rh);
  1381. hdrs->tag = 1;
  1382. break;
  1383. }
  1384. hdrs = hdrs->next;
  1385. }
  1386. if (q == NULL) break;
  1387. p = q+1;
  1388. }
  1389. free(b);
  1390. }
  1391. #ifdef PDKIM_DEBUG
  1392. if (ctx->debug_stream)
  1393. fprintf(ctx->debug_stream,
  1394. "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
  1395. #endif
  1396. /* SIGNING ---------------------------------------------------------------- */
  1397. if (ctx->mode == PDKIM_MODE_SIGN) {
  1398. /* Copy headernames to signature struct */
  1399. sig->headernames = strdup(headernames->str);
  1400. pdkim_strfree(headernames);
  1401. /* Create signature header with b= omitted */
  1402. sig_hdr = pdkim_create_header(ctx->sig,0);
  1403. }
  1404. /* VERIFICATION ----------------------------------------------------------- */
  1405. else {
  1406. sig_hdr = strdup(sig->rawsig_no_b_val);
  1407. }
  1408. /* ------------------------------------------------------------------------ */
  1409. if (sig_hdr == NULL) return PDKIM_ERR_OOM;
  1410. /* Relax header if necessary */
  1411. if (sig->canon_headers == PDKIM_CANON_RELAXED) {
  1412. char *relaxed_hdr = pdkim_relax_header(sig_hdr,0);
  1413. free(sig_hdr);
  1414. if (relaxed_hdr == NULL) return PDKIM_ERR_OOM;
  1415. sig_hdr = relaxed_hdr;
  1416. }
  1417. #ifdef PDKIM_DEBUG
  1418. if (ctx->debug_stream) {
  1419. fprintf(ctx->debug_stream,
  1420. "PDKIM >> Signed DKIM-Signature header, canonicalized >>>>>>>>>>>>>>>>>\n");
  1421. pdkim_quoteprint(ctx->debug_stream, sig_hdr, strlen(sig_hdr), 1);
  1422. fprintf(ctx->debug_stream,
  1423. "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
  1424. }
  1425. #endif
  1426. /* Finalize header hash */
  1427. if (sig->algo == PDKIM_ALGO_RSA_SHA1) {
  1428. sha1_update(&(sha1_headers),(unsigned char *)sig_hdr,strlen(sig_hdr));
  1429. sha1_finish(&(sha1_headers),(unsigned char *)headerhash);
  1430. #ifdef PDKIM_DEBUG
  1431. if (ctx->debug_stream) {
  1432. fprintf(ctx->debug_stream, "PDKIM [%s] hh computed: ", sig->domain);
  1433. pdkim_hexprint(ctx->debug_stream, headerhash, 20, 1);
  1434. }
  1435. #endif
  1436. }
  1437. else {
  1438. sha2_update(&(sha2_headers),(unsigned char *)sig_hdr,strlen(sig_hdr));
  1439. sha2_finish(&(sha2_headers),(unsigned char *)headerhash);
  1440. #ifdef PDKIM_DEBUG
  1441. if (ctx->debug_stream) {
  1442. fprintf(ctx->debug_stream, "PDKIM [%s] hh computed: ", sig->domain);
  1443. pdkim_hexprint(ctx->debug_stream, headerhash, 32, 1);
  1444. }
  1445. #endif
  1446. }
  1447. free(sig_hdr);
  1448. /* SIGNING ---------------------------------------------------------------- */
  1449. if (ctx->mode == PDKIM_MODE_SIGN) {
  1450. rsa_context rsa;
  1451. rsa_init(&rsa,RSA_PKCS_V15,0);
  1452. /* Perform private key operation */
  1453. if (rsa_parse_key(&rsa, (unsigned char *)sig->rsa_privkey,
  1454. strlen(sig->rsa_privkey), NULL, 0) != 0) {
  1455. return PDKIM_ERR_RSA_PRIVKEY;
  1456. }
  1457. sig->sigdata_len = mpi_size(&(rsa.N));
  1458. sig->sigdata = malloc(sig->sigdata_len);
  1459. if (sig->sigdata == NULL) return PDKIM_ERR_OOM;
  1460. if (rsa_pkcs1_sign( &rsa, RSA_PRIVATE,
  1461. ((sig->algo == PDKIM_ALGO_RSA_SHA1)?
  1462. SIG_RSA_SHA1:SIG_RSA_SHA256),
  1463. 0,
  1464. (unsigned char *)headerhash,
  1465. (unsigned char *)sig->sigdata ) != 0) {
  1466. return PDKIM_ERR_RSA_SIGNING;
  1467. }
  1468. rsa_free(&rsa);
  1469. #ifdef PDKIM_DEBUG
  1470. if (ctx->debug_stream) {
  1471. fprintf(ctx->debug_stream, "PDKIM [%s] b computed: ",
  1472. sig->domain);
  1473. pdkim_hexprint(ctx->debug_stream, sig->sigdata, sig->sigdata_len, 1);
  1474. }
  1475. #endif
  1476. sig->signature_header = pdkim_create_header(ctx->sig,1);
  1477. if (sig->signature_header == NULL) return PDKIM_ERR_OOM;
  1478. }
  1479. /* VERIFICATION ----------------------------------------------------------- */
  1480. else {
  1481. rsa_context rsa;
  1482. char *dns_txt_name, *dns_txt_reply;
  1483. rsa_init(&rsa,RSA_PKCS_V15,0);
  1484. dns_txt_name = malloc(PDKIM_DNS_TXT_MAX_NAMELEN);
  1485. if (dns_txt_name == NULL) return PDKIM_ERR_OOM;
  1486. dns_txt_reply = malloc(PDKIM_DNS_TXT_MAX_RECLEN);
  1487. if (dns_txt_reply == NULL) {
  1488. free(dns_txt_name);
  1489. return PDKIM_ERR_OOM;
  1490. }
  1491. memset(dns_txt_reply,0,PDKIM_DNS_TXT_MAX_RECLEN);
  1492. memset(dns_txt_name ,0,PDKIM_DNS_TXT_MAX_NAMELEN);
  1493. if (snprintf(dns_txt_name,PDKIM_DNS_TXT_MAX_NAMELEN,
  1494. "%s._domainkey.%s.",
  1495. sig->selector,sig->domain) >= PDKIM_DNS_TXT_MAX_NAMELEN) {
  1496. sig->verify_status = PDKIM_VERIFY_INVALID;
  1497. sig->verify_ext_status = PDKIM_VERIFY_INVALID_BUFFER_SIZE;
  1498. goto NEXT_VERIFY;
  1499. }
  1500. if ((ctx->dns_txt_callback(dns_txt_name, dns_txt_reply) != PDKIM_OK) ||
  1501. (dns_txt_reply[0] == '\0')) {
  1502. sig->verify_status = PDKIM_VERIFY_INVALID;
  1503. sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_UNAVAILABLE;
  1504. goto NEXT_VERIFY;
  1505. }
  1506. #ifdef PDKIM_DEBUG
  1507. if (ctx->debug_stream) {
  1508. fprintf(ctx->debug_stream,
  1509. "PDKIM >> Parsing public key record >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
  1510. fprintf(ctx->debug_stream,"Raw record: ");
  1511. pdkim_quoteprint(ctx->debug_stream, dns_txt_reply, strlen(dns_txt_reply), 1);
  1512. }
  1513. #endif
  1514. sig->pubkey = pdkim_parse_pubkey_record(ctx,dns_txt_reply);
  1515. if (sig->pubkey == NULL) {
  1516. sig->verify_status = PDKIM_VERIFY_INVALID;
  1517. sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_PARSING;
  1518. #ifdef PDKIM_DEBUG
  1519. if (ctx->debug_stream) {
  1520. fprintf(ctx->debug_stream,"Error while parsing public key record\n");
  1521. fprintf(ctx->debug_stream,
  1522. "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
  1523. }
  1524. #endif
  1525. goto NEXT_VERIFY;
  1526. }
  1527. #ifdef PDKIM_DEBUG
  1528. if (ctx->debug_stream) {
  1529. fprintf(ctx->debug_stream,
  1530. "PDKIM <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
  1531. }
  1532. #endif
  1533. if (rsa_parse_public_key(&rsa,
  1534. (unsigned char *)sig->pubkey->key,
  1535. sig->pubkey->key_len) != 0) {
  1536. sig->verify_status = PDKIM_VERIFY_INVALID;
  1537. sig->verify_ext_status = PDKIM_VERIFY_INVALID_PUBKEY_PARSING;
  1538. goto NEXT_VERIFY;
  1539. }
  1540. /* Check the signature */
  1541. if (rsa_pkcs1_verify(&rsa,
  1542. RSA_PUBLIC,
  1543. ((sig->algo == PDKIM_ALGO_RSA_SHA1)?
  1544. SIG_RSA_SHA1:SIG_RSA_SHA256),
  1545. 0,
  1546. (unsigned char *)headerhash,
  1547. (unsigned char *)sig->sigdata) != 0) {
  1548. sig->verify_status = PDKIM_VERIFY_FAIL;
  1549. sig->verify_ext_status = PDKIM_VERIFY_FAIL_MESSAGE;
  1550. goto NEXT_VERIFY;
  1551. }
  1552. /* We have a winner! (if bodydhash was correct earlier) */
  1553. if (sig->verify_status == PDKIM_VERIFY_NONE) {
  1554. sig->verify_status = PDKIM_VERIFY_PASS;
  1555. }
  1556. NEXT_VERIFY:
  1557. #ifdef PDKIM_DEBUG
  1558. if (ctx->debug_stream) {
  1559. fprintf(ctx->debug_stream, "PDKIM [%s] signature status: %s",
  1560. sig->domain, pdkim_verify_status_str(sig->verify_status));
  1561. if (sig->verify_ext_status > 0) {
  1562. fprintf(ctx->debug_stream, " (%s)\n",
  1563. pdkim_verify_ext_status_str(sig->verify_ext_status));
  1564. }
  1565. else {
  1566. fprintf(ctx->debug_stream, "\n");
  1567. }
  1568. }
  1569. #endif
  1570. rsa_free(&rsa);
  1571. free(dns_txt_name);
  1572. free(dns_txt_reply);
  1573. }
  1574. sig = sig->next;
  1575. }
  1576. /* If requested, set return pointer to signature(s) */
  1577. if (return_signatures != NULL) {
  1578. *return_signatures = ctx->sig;
  1579. }
  1580. return PDKIM_OK;
  1581. }
  1582. /* -------------------------------------------------------------------------- */
  1583. DLLEXPORT pdkim_ctx *pdkim_init_verify(int input_mode,
  1584. int(*dns_txt_callback)(char *, char *)
  1585. ) {
  1586. pdkim_ctx *ctx = malloc(sizeof(pdkim_ctx));
  1587. if (ctx == NULL) return NULL;
  1588. memset(ctx,0,sizeof(pdkim_ctx));
  1589. ctx->linebuf = malloc(PDKIM_MAX_BODY_LINE_LEN);
  1590. if (ctx->linebuf == NULL) {
  1591. free(ctx);
  1592. return NULL;
  1593. }
  1594. ctx->mode = PDKIM_MODE_VERIFY;
  1595. ctx->input_mode = input_mode;
  1596. ctx->dns_txt_callback = dns_txt_callback;
  1597. return ctx;
  1598. }
  1599. /* -------------------------------------------------------------------------- */
  1600. DLLEXPORT pdkim_ctx *pdkim_init_sign(int input_mode,
  1601. char *domain,
  1602. char *selector,
  1603. char *rsa_privkey) {
  1604. pdkim_ctx *ctx;
  1605. pdkim_signature *sig;
  1606. if (!domain || !selector || !rsa_privkey) return NULL;
  1607. ctx = malloc(sizeof(pdkim_ctx));
  1608. if (ctx == NULL) return NULL;
  1609. memset(ctx,0,sizeof(pdkim_ctx));
  1610. ctx->linebuf = malloc(PDKIM_MAX_BODY_LINE_LEN);
  1611. if (ctx->linebuf == NULL) {
  1612. free(ctx);
  1613. return NULL;
  1614. }
  1615. sig = malloc(sizeof(pdkim_signature));
  1616. if (sig == NULL) {
  1617. free(ctx->linebuf);
  1618. free(ctx);
  1619. return NULL;
  1620. }
  1621. memset(sig,0,sizeof(pdkim_signature));
  1622. sig->bodylength = -1;
  1623. ctx->mode = PDKIM_MODE_SIGN;
  1624. ctx->input_mode = input_mode;
  1625. ctx->sig = sig;
  1626. ctx->sig->domain = strdup(domain);
  1627. ctx->sig->selector = strdup(selector);
  1628. ctx->sig->rsa_privkey = strdup(rsa_privkey);
  1629. if (!ctx->sig->domain || !ctx->sig->selector || !ctx->sig->rsa_privkey) {
  1630. pdkim_free_ctx(ctx);
  1631. return NULL;
  1632. }
  1633. ctx->sig->sha1_body = malloc(sizeof(sha1_context));
  1634. if (ctx->sig->sha1_body == NULL) {
  1635. pdkim_free_ctx(ctx);
  1636. return NULL;
  1637. }
  1638. sha1_starts(ctx->sig->sha1_body);
  1639. ctx->sig->sha2_body = malloc(sizeof(sha2_context));
  1640. if (ctx->sig->sha2_body == NULL) {
  1641. pdkim_free_ctx(ctx);
  1642. return NULL;
  1643. }
  1644. sha2_starts(ctx->sig->sha2_body,0);
  1645. return ctx;
  1646. }
  1647. #ifdef PDKIM_DEBUG
  1648. /* -------------------------------------------------------------------------- */
  1649. DLLEXPORT void pdkim_set_debug_stream(pdkim_ctx *ctx,
  1650. FILE *debug_stream) {
  1651. ctx->debug_stream = debug_stream;
  1652. }
  1653. #endif
  1654. /* -------------------------------------------------------------------------- */
  1655. DLLEXPORT int pdkim_set_optional(pdkim_ctx *ctx,
  1656. char *sign_headers,
  1657. char *identity,
  1658. int canon_headers,
  1659. int canon_body,
  1660. long bodylength,
  1661. int algo,
  1662. unsigned long created,
  1663. unsigned long expires) {
  1664. if (identity != NULL) {
  1665. ctx->sig->identity = strdup(identity);
  1666. if (ctx->sig->identity == NULL) return PDKIM_ERR_OOM;
  1667. }
  1668. if (sign_headers != NULL) {
  1669. ctx->sig->sign_headers = strdup(sign_headers);
  1670. if (ctx->sig->sign_headers == NULL) return PDKIM_ERR_OOM;
  1671. }
  1672. ctx->sig->canon_headers = canon_headers;
  1673. ctx->sig->canon_body = canon_body;
  1674. ctx->sig->bodylength = bodylength;
  1675. ctx->sig->algo = algo;
  1676. ctx->sig->created = created;
  1677. ctx->sig->expires = expires;
  1678. return PDKIM_OK;
  1679. }