x400_msrcv_msg_tok_sign.c
1 /* Copyright (c) 2009-2011, Isode Limited, London, England.
2  * All rights reserved.
3  *
4  * Acquisition and use of this software and related materials for any
5  * purpose requires a written licence agreement from Isode Limited,
6  * or a written licence from an organisation licenced by Isode Limited
7  * to grant such a licence.
8  *
9  */
10 
11 /*
12  *
13  * @VERSION@
14  *
15  * Simple example program for receiving a message from a store.
16  * The security environment is set up so that signed messages
17  * will have per message MOAC signatures and recipient Message Token
18  * signatures verified.
19  *
20  * Note that a valid Digital Identity is no longer required in order to
21  * perform verification. Instead the name of a directory containing trusted,
22  * self signed certificates in DER form can be passed in.
23  */
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <x400_msapi.h>
28 #include "example.h"
29 #include "ms_example.h"
30 #include <seclabel_api.h> /* For security labels */
31 
32 #define XML_BUFSIZE 1024
33 
34 int num_unsigned_rcvd;
35 int num_unverified_rcvd;
36 int num_verified_rcvd;
37 int num_messages_rcvd ;
38 int num_reports_rcvd ;
39 int num_ipns_rcvd ;
40 
41 static char *optstr = "u37m:d:p:w:M:D:P:W:e:b:x:EY:U:I";
42 
43 static void usage(void);
44 
45 
46 static int get_msg(
47  struct X400msSession *sp
48 );
49 
50 static void setup_default_new_sec_env(
51  struct X400msSession *sp,
52  char *sec_trusted_cert_dir
53 );
54 
55 static void setup_default_old_sec_env(
56  struct X400msSession *sp,
57  char *id,
58  char *dn,
59  char *pw /* passphrase for private key in pkcs12 file */
60 );
61 
62 static void report_msg_token_info(
63  struct X400Recipient *rp
64 );
65 
66 static int get_sec_label(
67  struct X400msMessage *mp
68 );
69 
70 static void print_sec_label(
71  unsigned char slab_buffer[],
72  unsigned int length
73 );
74 
75 static int get_cic(
76  struct X400Recipient *rp
77 );
78 
79 static void show_certificate (
80  struct X400Recipient *rp,
81  int certtype,
82  const char *tag
83 );
84 
85 static int handle_ipn(
86  struct X400msMessage *mp
87 );
88 
89 static int handle_msg(
90  struct X400msSession *sp,
91  struct X400msMessage *mp
92 );
93 
94 static int send_ipn(
95  struct X400msSession *sp,
96  struct X400msMessage *mp,
97  struct X400msMessage **ipn
98 );
99 
100 static int do_report(
101  struct X400msSession *sp,
102  struct X400msMessage *mp
103 );
104 
108 int
109 main(
110  int argc,
111  char **argv)
112 {
113  char buffer[BUFSIZ];
114  char pa[BUFSIZ];
115  char orn[BUFSIZ];
116  int status;
117  int nummsg;
118  struct X400msSession *sp;
119  int contype;
120  char *def_oraddr;
121  char *def_dn;
122  char *def_pa;
123 
124  if (get_args(argc, argv, optstr)) {
125  usage();
126  exit(-1);
127  }
128 
129  printf("Connection type (0 = P7, 1 = P3 submit only, 2 = P3 both directions) [%d]: ", x400_contype);
130  contype = ic_fgetc(x400_contype, stdin);
131  if (contype != 10)
132  ic_fgetc(x400_contype, stdin);
133 
134  if ( contype < '0' || '2' < contype )
135  contype = x400_contype;
136  else
137  contype -= '0';
138 
139  if (contype == 0) {
140  def_oraddr = x400_ms_user_addr;
141  def_dn = x400_ms_user_dn;
142  def_pa = x400_ms_presentation_address;
143  }
144  else {
145  def_oraddr = x400_mta_user_addr;
146  def_dn = x400_mta_user_dn;
147  def_pa = x400_mta_presentation_address;
148  }
149 
150  printf("Your ORAddress [%s] > ", def_oraddr);
151  ic_fgets(orn, sizeof orn, stdin);
152 
153  if (orn[strlen(orn) - 1] == '\n')
154  orn[strlen(orn) - 1] = '\0';
155 
156  if (orn[0] == '\0')
157  strcpy(orn, def_oraddr);
158 
159  /* Prompt for password; note: reflected. */
160  printf("Password [%s]: ",
161  contype == 0 ? x400_p7_password : x400_p3_password);
162  if (ic_fgets(buffer, sizeof buffer, stdin) == NULL)
163  exit(1);
164 
165  if (buffer[strlen(buffer) - 1] == '\n')
166  buffer[strlen(buffer) - 1] = '\0';
167  if (buffer[0] == '\0')
168  strcpy(buffer, contype == 0 ? x400_p7_password : x400_p3_password);
169 
170  printf("Presentation Address [%s] > ", def_pa);
171  ic_fgets(pa, sizeof pa, stdin);
172 
173  if (pa[strlen(pa) - 1] == '\n')
174  pa[strlen(pa) - 1] = '\0';
175 
176  if (pa[0] == '\0')
177  strcpy(pa, def_pa);
178 
179  status = X400msOpen(contype, orn, def_dn, buffer, pa, &nummsg, &sp);
180  if (status != X400_E_NOERROR) {
181  fprintf(stderr, "Error in Open: %s\n", X400msError(status));
182  exit(status);
183  }
184 
185  /* setup logging from $(ETCDIR)x400api.xml or $(SHAREDIR)x400api.xml */
186  X400msSetStrDefault(sp, X400_S_LOG_CONFIGURATION_FILE, "x400api.xml", 0);
187 
188  if (nummsg == 0) {
189  printf ("no messages - waiting for a message to be delivered.....\n");
190  }
191  else {
192  printf("%d messages waiting\n", nummsg);
193  }
194 
195  status = get_msg(sp);
196  if (status != X400_E_NOERROR) {
197  fprintf(stderr, "Error in getting msg: %s\n",
198  X400msError(status));
199  exit(status);
200  }
201  fprintf(stderr, "got first\n");
202 
203  do {
204  fprintf(stderr, "================================================\n");
205  status = get_msg(sp);
206  if (status != X400_E_NOERROR) {
207  fprintf(stderr, "Error in getting msg: %s\n",
208  X400msError(status));
209  exit(status);
210  }
211  } while (until_no_more_msgs);
212 
213  status = X400msClose(sp);
214  printf("%d num_messages_rcvd\n", num_messages_rcvd);
215  printf("%d num_reports_rcvd\n", num_reports_rcvd);
216  printf("%d num_unsigned_rcvd\n", num_unsigned_rcvd);
217  printf("%d num_unverified_rcvd\n", num_unverified_rcvd);
218  printf("%d num_verified_rcvd\n", num_verified_rcvd);
219  printf("%d num_ipns_rcvd\n", num_ipns_rcvd);
220  return(status);
221 }
222 
223 
224 static int get_msg(
225  struct X400msSession *sp
226 )
227 {
228  int status;
229  int nummsg;
230  int type;
231  int seqn;
232  struct X400msMessage *mp;
233  int intparam;
234 
235  printf("Waiting for new messages for 10 seconds\n");
236  status = X400msWait(sp, 10, &nummsg);
237  if (status != X400_E_NOERROR) {
238  fprintf(stderr, "Error from Wait: %s\n", X400msError(status));
239  /* tidily close the session */
240  status = X400msClose(sp);
241  printf("%d num_messagese_rcvd\n", num_messages_rcvd);
242  printf("%d num_reports_rcvd\n", num_reports_rcvd);
243  printf("%d num_unsigned_rcvd\n", num_unsigned_rcvd);
244  printf("%d num_unverified_rcvd\n", num_unverified_rcvd);
245  printf("%d num_verified_rcvd\n", num_verified_rcvd);
246  exit(status);
247  }
248 
249  /* Set up the security environment.
250  *
251  * In R15.0 this need only be the name of a trusted certificate directory.
252  *
253  * Prior to R15.0, the ID is specified as a pathname, in which the
254  * subdirectory "x509" is expected to contain one or more PKCS12
255  * files. The appropriate Digital Identity is determined from the
256  * DN of the subject, and the passphrase is used to decrypt the
257  * private key. NB even though we're not going to use our cert,
258  * (as we're going to use the cert in the message to check the MOAC
259  * we need to do this due to a limitation in the underlying X.509
260  * layer.
261  */
262  if (use_new_sec_env) {
263  setup_default_new_sec_env(sp, trusted_ca_certs_dir);
264  } else {
265  setup_default_old_sec_env(sp, security_id, identity_dn, passphrase);
266  }
267 
268  /* Turn off legacy bahaviour in which MOAC verification failure
269  * returns X400_E_NOERROR.
270  * We will now get X400_E_X509_VERIFY_FAILURE from MsgGet
271  * if/when the verification fails
272  */
274 
275  printf("Getting message\n");
276 
277  status = X400msMsgGet(sp, 0, &mp, &type, &seqn);
278  switch (status) {
279  case X400_E_NOERROR:
280  fprintf(stderr, "MsgGet successfully got message\n");
281  break;
282  default :
283  fprintf(stderr, "Error from MsgGet: %s\n", X400msError(status));
284  /* tidily close the session */
285  status = X400msClose(sp);
286  exit(status);
287  break;
288  }
289 
290  if (type != X400_MSG_MESSAGE) {
291  /**********************************/
292  /* Report on the received Report */
293  /**********************************/
294  status = do_report(sp, mp);
295  return (status);
296  }
297 
298  /**********************************/
299  /* Report on the received Message */
300  /**********************************/
301 
302  status = X400msMsgGetIntParam(mp, X400_N_IS_IPN, &intparam);
303  if (status != X400_E_NOERROR) {
304  fprintf(stderr, "Error from MsgGetIntParam: %s\n",
305  X400msError(status));
306  }
307  printf("Type of Message: %d\n", intparam);
308  if (intparam != 0) {
309  /**********************************/
310  /* Report on the received IPN */
311  /**********************************/
312  printf("Received an IPN\n");
313  num_ipns_rcvd++;
314  handle_ipn(mp);
315  status = X400msMsgDelete(mp, 0);
316  } else {
317  printf("not an IPN\n");
318  num_messages_rcvd++ ;
319  status = handle_msg(sp, mp);
320  if (status != X400_E_NOERROR) {
321  fprintf(stderr, "Error from handle_msg: %s\n",
322  X400msError(status));
323  return status;
324  }
325  if (gen_ipn) {
326  struct X400msMessage *ipn;
327  status = send_ipn(sp, mp, &ipn);
328  if (status != X400_E_NOERROR) {
329  fprintf(stderr, "Error from send_ipn: %s\n",
330  X400msError(status));
331  }
332  /* Deletes message in message store as well as internal copy */
333  status = X400msMsgDelete(mp, 0);
334  if (status != X400_E_NOERROR) {
335  fprintf(stderr, "Error from X400msMsgDelete (IPN)%s\n",
336  X400msError(status));
337  }
338 
339  status = X400msMsgDelete(ipn, 0);
340  if (status != X400_E_NOERROR) {
341  fprintf(stderr, "Error from X400msMsgDelete (IPN)%s\n",
342  X400msError(status));
343  }
344  return status;
345  } else {
346  /* Deletes message in message store as well as internal copy */
347  status = X400msMsgDelete(mp, 0);
348  if (status != X400_E_NOERROR) {
349  fprintf(stderr, "Error from X400msMsgDelete (IPN)%s\n",
350  X400msError(status));
351  }
352  return status;
353  }
354  }
355  return X400_E_NOERROR;
356 }
357 
358 static int do_report(
359  struct X400msSession *sp,
360  struct X400msMessage *mp
361 )
362 {
363  char buffer[BUFSIZ];
364  size_t length;
365  int intparam;
366  char recipient_str[BUFSIZ];
367  int status;
368  int n;
369  struct X400Recipient *rp;
370 
371  /**********************************/
372  /* Report on the received Report */
373  /**********************************/
374  num_reports_rcvd++ ;
375  fprintf(stderr, "Got a report (printing only some attributes)\n");
376 
377  /* The ORADDRESS in the message is the (envelope) originator */
379  buffer, sizeof buffer, &length);
380  if (status != X400_E_NOERROR) {
381  fprintf(stderr, "Error from MsgGetStrParam: %s\n",
382  X400msError(status));
383  /* tidily close the session */
384  status = X400msClose(sp);
385  exit(status);
386  }
387  printf("Subject Identifier: %.*s\n", (int)length, buffer);
388 
389  /* Get the primary recipients */
390  for (n = 1;; n++) {
391  status = X400msRecipGet(mp, X400_RECIP_REPORT, n, &rp);
392  if (status == X400_E_NO_RECIP)
393  break;
394  if (status != X400_E_NOERROR) {
395  fprintf(stderr, "Error from RecipGet: %s\n",
396  X400msError(status));
397  /* tidily close the session */
398  status = X400msClose(sp);
399  exit(status);
400  }
401 
402  /* Note: recipient may not actually have an O/R address */
404  recipient_str,
405  sizeof recipient_str, &length);
406  if (status != X400_E_NOERROR) {
407  fprintf(stderr, "Error from RecipGetStrParam: %s\n",
408  X400msError(status));
409  /* tidily close the session */
410  status = X400msClose(sp);
411  exit(status);
412  }
413  /* print out the O/R Address of the report */
414  printf("Delivery Report for recipient %d: %.*s\n", n,
415  (int)length, recipient_str);
416 
417  /* The original message delivery time, if this attribute exists,
418  * then the report is a positive Delivery Report */
420  buffer, sizeof buffer, &length);
421 
422  if (status == X400_E_NOERROR) {
423  /* Positive Delivery Report */
424  printf("Delivery Time: %.*s\n", (int)length, buffer);
425  }
426  else {
427  /* Negative Delivery Report */
428  printf("Negative Delivery Report for recipient %d: %.*s\n", n,
429  (int)length, recipient_str);
430 
431  /* Supplementary Info to the report */
433  buffer, sizeof buffer,
434  &length);
435  if (status != X400_E_NOERROR) {
436  fprintf(stderr, "Error from RecipGetStrParam: %s\n",
437  X400msError(status));
438  buffer[0] = '\0';
439  }
440  printf("Supplementary Info: %.*s\n", (int)length, buffer);
441 
442  /* The reason why the message was not delivered */
443  status =
445  &intparam);
446  if (status != X400_E_NOERROR) {
447  fprintf(stderr, "Error from RecipGetIntParam: %s\n",
448  X400msError(status));
449  }
450  printf("Non-Delivery Reason: %d\n", intparam);
451 
452  /* The diagnostics of the report for this recipient */
453  status =
455  &intparam);
456  if (status != X400_E_NOERROR) {
457  fprintf(stderr, "Error from RecipGetIntParam: %s\n",
458  X400msError(status));
459  }
460  printf("Non-Delivery Diagnostic: %d\n", intparam);
461  }
462  }
463 
464  status = X400msMsgDelete(mp, 0);
465  if (status != X400_E_NOERROR) {
466  fprintf(stderr, "Error from X400msMsgDelete: %s\n",
467  X400msError(status));
468  }
469  return status;
470 }
471 
472 static int handle_ipn(
473  struct X400msMessage *mp
474 )
475 {
476  struct X400Recipient *rp;
477  int status;
478  char buffer[BUFSIZ];
479  size_t length;
480  int intparam;
481 
482 
483  /* The X400_S_OR_ADDRESS in the message is the IPN originator */
484  /* not clear why X400_ORIGINATOR doesn;t work */
486  buffer, sizeof buffer, &length);
487  if (status != X400_E_NOERROR) {
488  fprintf(stderr, "Error from MsgGetStrParam (X400_S_OR_ADDRESS): %s\n",
489  X400msError(status));
490  } else {
491  printf("IPN Originator: %.*s\n", (int)length, buffer);
492  }
493 
494  /* Obtain the envelope recipient address */
495  status = X400msRecipGet (mp, X400_RECIP_ENVELOPE, 1, &rp);
496  if ( status != X400_E_NOERROR ) {
497  fprintf(stderr, "Error from X400msRecipGet (X400_RECIP_ENVELOPE): %s\n",
498  X400msError(status));
499  } else {
501  buffer, sizeof buffer, &length);
502  if ( status != X400_E_NOERROR ) {
503  fprintf(stderr, "Error from X400RecipGetStrParam (X400_S_OR_ADDRESS): %s\n",
504  X400msError(status));
505  } else {
506 
507  buffer[length] = '\0';
508  printf("IPN Recipient: %.*s\n", (int)length, buffer);
509  }
510  }
511 
512 
513  /* The subject message identifier */
515  buffer, sizeof buffer, &length);
516  if (status != X400_E_NOERROR) {
517  fprintf(stderr, "Error from MsgGetStrParam (X400_S_SUBJECT_IPM): %s\n",
518  X400msError(status));
519  } else {
520  printf("Subject Message Identifier: %.*s\n", (int)length, buffer);
521  }
522 
523  /* The conversion EITs */
525  buffer, sizeof buffer, &length);
526  if (status != X400_E_NOERROR) {
527  fprintf(stderr, "Error from MsgGetStrParam (X400_S_CONVERSION_EITS): %s\n", X400msError(status));
528  } else {
529  printf("conversion EITs: %.*s\n", (int)length, buffer);
530  }
531 
532  /* non-receipt reason */
534  &intparam);
535  if (status == X400_E_NOERROR) {
536  printf(" non-receipt reason: %d\n", intparam);
537  } else {
538  fprintf(stderr, "Error getting non-receipt reason: %s\n",
539  X400msError(status));
540  }
541 
542  /* discard reason */
544  &intparam);
545  if (status == X400_E_NOERROR) {
546  printf("discard reason: %d\n", intparam);
547  } else {
548  fprintf(stderr, "Error getting discard reason: %s\n",
549  X400msError(status));
550  }
551 
552  /* Autoforward comment */
554  buffer, sizeof buffer, &length);
555  if (status != X400_E_NOERROR) {
556  fprintf(stderr, "Error from MsgGetStrParam (X400_S_AUTOFORWARD_COMMENT): %s\n",
557  X400msError(status));
558  } else {
559  printf("autoforward comment: %.*s\n", (int)length, buffer);
560  }
561 
562  /* Time of receipt: UTCTime format */
564  buffer, sizeof buffer, &length);
565  if (status != X400_E_NOERROR) {
566  fprintf(stderr, "Error from MsgGetStrParam(X400_S_RECEIPT_TIME): %s\n",
567  X400msError(status));
568  } else {
569  printf(" Time of receipt: (UTCTime format): %.*s\n", (int)length, buffer);
570  }
571 
572  /* Acknowledgement mode: 0 - manual; 1 -automatic */
574  &intparam);
575  if (status == X400_E_NOERROR) {
576  printf(" Acknowledgement mode: (0 - manual; 1 -automatic): %d\n",
577  intparam);
578  } else {
579  fprintf(stderr, "Error getting Acknowledgement mode: %s\n",
580  X400msError(status));
581  }
582 
583  /* Supplementary information associated with IPN */
585  buffer, sizeof buffer, &length);
586  if (status != X400_E_NOERROR) {
587  fprintf(stderr, "Error from MsgGetStrParam (X400_S_SUPP_RECEIPT_INFO): %s\n",
588  X400msError(status));
589  /* tidily close the session */
590  /* status = X400msClose(sp);
591  exit(status);
592  */
593  } else {
594  printf(" Supplementary information: %.*s\n", (int)length, buffer);
595  }
596  status = X400msMsgGetIntParam(mp, X400_N_CONTENT_TYPE, &intparam);
597  if (status != X400_E_NOERROR) {
598  fprintf(stderr,
599  "Error from MsgGetIntParam (X400_N_CONTENT_TYPE,): %s\n",
600  X400msError(status));
601  } else {
602  printf("Content Type: %d\n", intparam);
603  }
604 
605 
606 
607  return X400_E_NOERROR;
608 }
609 
610 
611 static int handle_msg(
612  struct X400msSession *sp,
613  struct X400msMessage *mp
614 )
615 {
616  int status;
617  int intparam;
618  size_t length;
619  char buffer[BUFSIZ];
620  struct X400Recipient *rp;
621  int n;
622 
623  /* Size */
624  status =
626  &intparam);
627  if (status != X400_E_NOERROR) {
628  fprintf(stderr, "Error from MsgGetIntParam: %s\n",
629  X400msError(status));
630  }
631  printf("Size of Message: %d\n", intparam);
632 
633  /* The message identifier */
635  buffer, sizeof buffer, &length);
636  if (status != X400_E_NOERROR) {
637  fprintf(stderr, "Error from MsgGetStrParam: %s\n",
638  X400msError(status));
639  /* tidily close the session */
640  status = X400msClose(sp);
641  exit(status);
642  }
643  printf("Message Identifier: %.*s\n", (int)length, buffer);
644 
645  /* The ORADDRESS in the message is the (envelope) originator */
647  buffer, sizeof buffer, &length);
648  if (status != X400_E_NOERROR) {
649  fprintf(stderr, "Error from MsgGetStrParam: %s\n",
650  X400msError(status));
651  /* tidily close the session */
652  status = X400msClose(sp);
653  exit(status);
654  }
655  printf("Originator: %.*s\n", (int)length, buffer);
656 
657  /* Get the envelope recipients */
658  for (n = 1;; n++) {
659  status = X400msRecipGet(mp, X400_RECIP_ENVELOPE, n, &rp);
660  if (status == X400_E_NO_RECIP)
661  break;
662  if (status != X400_E_NOERROR) {
663  fprintf(stderr, "Error from RecipGet: %s\n", X400msError(status));
664  /* tidily close the session */
665  status = X400msClose(sp);
666  exit(status);
667  }
668 
669  /* Note: recipient may not actually have an O/R address */
671  buffer, sizeof buffer, &length);
672  if (status == X400_E_NOERROR) {
673  printf("Env Recipient %d: %.*s\n", n, (int)length, buffer);
674  }
675 
676  /* get back status of the Proof Of Del Request in the recipient */
678  &intparam);
679  if (status == X400_E_NOERROR) {
680  printf("Recipient proof of delivery request is %d\n", intparam);
681  } else {
682  fprintf(stderr, "Error getting proof of delivery request: %s\n",
683  X400msError(status));
684  }
685 
686  /* report content integrity check info if available */
687  get_cic(rp);
688 
689  /* return MessageToken info if available */
690  report_msg_token_info(rp);
691 
692  /* get and display the seccurity label if available */
693  get_sec_label(mp);
694  }
695 
696  /* Get the primary recipients */
697  for (n = 1;; n++) {
698  status = X400msRecipGet(mp, X400_RECIP_PRIMARY, n, &rp);
699  if (status == X400_E_NO_RECIP)
700  break;
701  if (status != X400_E_NOERROR) {
702  fprintf(stderr, "Error from RecipGet: %s\n", X400msError(status));
703  /* tidily close the session */
704  status = X400msClose(sp);
705  exit(status);
706  }
707 
708  /* Note: recipient may not actually have an O/R address */
710  buffer, sizeof buffer, &length);
711  if (status == X400_E_NOERROR) {
712  printf("Primary Recipient %d: %.*s\n", n, (int)length, buffer);
713  }
714 
715  status = X400msRecipGetIntParam(rp, X400_N_PRECEDENCE, &intparam);
716  if (status == X400_E_NOERROR) {
717  printf("Primary Recipient Precedence %d\n", intparam);
718  } else {
719  fprintf(stderr, "Error from RecipGet: %s\n", X400msError(status));
720  }
721 
722  }
723 
724  /* Subject is optional */
726  buffer, sizeof buffer, &length);
727  if (status == X400_E_NOERROR)
728  printf("Subject: %.*s\n", (int)length, buffer);
729 
730  /* And message text (or it could be another type) */
732  buffer, sizeof buffer, &length);
733  if (status == X400_E_NOERROR)
734  printf("Text:\n%.*s\n", (int)length, buffer);
735  else
736  printf("No IA5 Text content (%d: %s)\n", status, X400msError(status));
737 
738  /* get all the attachments */
739  printf("Getting body parts\n");
740  get_body_parts(mp);
741 
742  return X400_E_NOERROR;
743 }
744 
745 
746 static int send_ipn(
747  struct X400msSession *sp,
748  struct X400msMessage *mp,
749  struct X400msMessage **ipn
750 )
751 {
752  int status;
753  status = X400msMsgNew (sp, X400_MSG_MESSAGE, ipn);
754  if ( status != X400_E_NOERROR ) {
755  fprintf (stderr, "x400msMsgNew returned error: %s\n",
756  X400msError (status));
757  return (status);
758  }
759 
760  status = X400msMakeIPN(mp, -1, ipn);
761  if (status != X400_E_NOERROR) {
762  fprintf(stderr, "Error from X400msMakeIPN: %s\n",
763  X400msError(status));
764  return status;
765  }
766 
767  /* submit */
768  status = X400msMsgSend (*ipn);
769  if ( status != X400_E_NOERROR ) {
770  fprintf (stderr, "x400msMsgSend returned error: %s\n",
771  X400msError (status));
772  return (status);
773  } else {
774  printf("IPN submitted successfully\n");
775  }
776 
777  return status;
778 }
779 /*
780  * Recommended function to setup security env for verification.
781  * No digitial ID required - just a directory which contains
782  * trust anchors which are read as DER file (certificate.crt).
783  *
784  * The certificate (containing public key) is obtained from the message
785  * which is referenced in the message.
786  */
787 
788 static void setup_default_new_sec_env(
789  struct X400msSession *sp,
790  char *local_trusted_ca_certs_dir
791 )
792 {
793  int status;
794 
795  /* Directory containing trusted CA Certificates */
796  printf(" Adding %s as trusted CA cert dir\n", trusted_ca_certs_dir);
798  local_trusted_ca_certs_dir, -1);
799  if ( status != X400_E_NOERROR ) {
800  fprintf (stderr, "X400msSetStrDefault returned error: %s\n",
801  X400msError (status));
802  exit (status);
803  }
804 
805  return;
806 }
807 
808 /*
809  * Obsolete function to use to set up the security environment. This provides a
810  * directory in which PKCS12 files are checked to find one whose subject DN
811  * matches that of this client.
812  *
813  * Any self signed certificates found in the directory are treated as
814  * trusted.
815  */
816 
817 static void setup_default_old_sec_env(
818  struct X400msSession *sp,
819  char *id,
820  char *dn,
821  char *pw /* passphrase for private key in pkcs12 file */
822 )
823 {
824  int status;
825 
826  /* first set a default security identity. This passes in the name of a
827  * directory, which contains an x509 subdirectory in which all Identities
828  * are held */
829  /* X400msSetStrDefault(sp, X400_S_SEC_IDENTITY, "/var/isode/dsa-db/", -1);
830  * */
832 
833  /* select by DN which Identity is to be used (if there are several)
834  * Currently these must be PKCS12 files */
835  status = X400msSetStrDefault (sp, X400_S_SEC_IDENTITY_DN, dn, -1);
836  if ( status != X400_E_NOERROR ) {
837  fprintf (stderr, "X400msSetStrDefault returned error: %s\n",
838  X400msError (status));
839  exit (status);
840  }
841 
842  /* passphrase used to open the Identity */
844  if ( status != X400_E_NOERROR ) {
845  fprintf (stderr, "X400msSetStrDefault returned error: %s\n",
846  X400msError (status));
847  exit (status);
848  }
849  return;
850 }
851 
852 static void report_msg_token_info(
853  struct X400Recipient *rp
854 )
855 {
856  char buffer[BUFSIZ];
857  int status;
858  int param;
859  size_t length;
860 
861  status = X400msRecipGetIntParam(rp,
862  X400_N_MSGTOK_STATUS, &param);
863  if (status == X400_E_NO_VALUE) {
864  fprintf(stderr, "No MessageToken present in recipient\n");
865  /* no further information available */
866  return ;
867  } else if (status != X400_E_NOERROR) {
868  fprintf(stderr, "Error from RecipGetIntParam: %s (%d)\n",
869  X400msError(status),
871  fprintf(stderr, "Message Token status not available\n");
872  } else {
873  fprintf(stderr,
874  "Message Token status %d \n", param);
875  }
876 
877  switch (param) {
878  case X400_E_NOERROR:
879  fprintf(stderr, "Token OK (%d)\n", param);
880  break;
881  case X400_E_X509_ENV:
882  case X400_E_X509_INIT:
883  fprintf(stderr,
884  "Message Token validation cannot take place because the security environment is invalid (%d):\n",
885  param);
886  /* other values will not be available */
887  return ;
895  fprintf(stderr,
896  "Message Token validation failed (%d): %s\n",
897  param, X400msError(param));
898  break;
899  default:
900  fprintf(stderr,
901  "Unexpected Message Token validation result (%d): %s\n",
902  param, X400msError(param));
903  break;
904 
905  }
906 
907  show_certificate (rp, X400_N_CERT_MSGTOK, "message-token");
908 
909  status = X400msRecipGetStrParam(rp,
911  buffer, sizeof buffer, &length);
912  if (status != X400_E_NOERROR) {
913  fprintf(stderr, "Error from RecipGetStrParam: %s\n",
914  X400msError(status));
915 
916  fprintf(stderr, "recipient in token not available\n");
917  } else {
918  fprintf(stderr,
919  "Message Token(%u): recipient in Token '%.*s'\n",
920  (unsigned)length, (int)length, buffer);
921  }
922 
923  status = X400msRecipGetStrParam(rp,
925  buffer, sizeof buffer, &length);
926  if (status != X400_E_NOERROR) {
927  fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
928  X400msError(status),
930  fprintf(stderr, "Message Token DER not available\n");
931  } else {
932  fprintf(stderr,
933  "Message Token DER available (%u bytes)\n", (unsigned)length);
934  }
935 
936  status = X400msRecipGetIntParam(rp,
937  X400_N_MSGTOK_SEQ_NUM, &param);
938  if (status != X400_E_NOERROR) {
939  fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
940  X400msError(status),
942  fprintf(stderr, "Message Token seq num not available\n");
943  } else {
944  fprintf(stderr,
945  "Message Token seq num %d \n", param);
946  }
947 
948  status = X400msRecipGetStrParam(rp,
950  buffer, sizeof buffer, &length);
951  if (status != X400_E_NOERROR) {
952  fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
953  X400msError(status),
955  fprintf(stderr, "Message Token Security Label DER not available\n");
956  } else {
957  fprintf(stderr,
958  "Message Token Security Label DER available (%u bytes)\n", (unsigned)length);
959  fprintf(stderr, "Security Label from Message Token is:\n");
960  print_sec_label((unsigned char *)buffer, length);
961  }
962 
963  /* get back status of the Content Integrity Check in the message token */
965  &param);
966  if (status == X400_E_NO_VALUE) {
967  printf("No Content Integrity Check in token\n");
968  } else if (status != X400_E_NOERROR) {
969  printf("Error from RecipGetIntParam: %s\n", X400msError(status));
970 
971  } else {
972 
973  /* report CIC information */
974  switch (param) {
975  case X400_E_NOERROR:
976  printf("Content Integrity Check in token succeeded\n");
977  break;
978  default:
979  printf("Content Integrity Check in token error (%d): %s\n",
980  param, X400msError(param));
981  break;
982  }
983 
984  status = X400msRecipGetStrParam(rp,
986  buffer, sizeof buffer, &length);
987  if (status != X400_E_NOERROR) {
988  fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
989  X400msError(status),
991  fprintf(stderr, "Message Token Content Integrity Check DER not available\n");
992  } else {
993  fprintf(stderr,
994  "Message Token Content Integrity Check DER available (%u bytes)\n",
995  (unsigned)length);
996  }
997 
998  show_certificate (rp, X400_N_CERT_MSGTOK_CIC, "token CIC");
999  }
1000 
1001  status = X400msRecipGetIntParam(rp,
1002  X400_N_MSGTOK_PODR_STATUS, &param);
1003  if (status != X400_E_NOERROR) {
1004  fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
1005  X400msError(status),
1007  fprintf(stderr, "Message Token proof of delivery status not available\n");
1008  } else {
1009  fprintf(stderr,
1010  "Message Token proof of delivery status %d \n", param);
1011  }
1012 
1013  status = X400msRecipGetIntParam(rp,
1015  if (status != X400_E_NOERROR) {
1016  fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
1017  X400msError(status),
1019  fprintf(stderr, "Message Token security label status not available\n");
1020  } else {
1021  fprintf(stderr,
1022  "Message Token security label status %d \n", param);
1023  }
1024 
1025  status = X400msRecipGetIntParam(rp,
1026  X400_N_MSGTOK_RECIP_STATUS, &param);
1027  if (status != X400_E_NOERROR) {
1028  fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
1029  X400msError(status),
1031  fprintf(stderr, "Message Token recip status not available\n");
1032  } else {
1033  fprintf(stderr,
1034  "Message Token recip status %d \n", param);
1035  }
1036 
1037 
1038  return;
1039 }
1040 
1041 
1042 static int get_sec_label(
1043  struct X400msMessage *mp
1044 )
1045 {
1046  unsigned char slab_buffer[XML_BUFSIZE];
1047  int status;
1048  size_t length;
1049 
1050  status = X400msMsgGetStrParam(mp,
1052  (char*)slab_buffer,
1053  XML_BUFSIZE,
1054  &length);
1055  if (status == X400_E_NO_VALUE) {
1056  printf("No security label\n");
1057  } else if (status != X400_E_NOERROR) {
1058  fprintf(stderr,"Failed to fetch security label: %d",status);
1059  return (status);
1060  } else {
1061  fprintf(stderr, "Security Label from envelope is:\n");
1062  print_sec_label(slab_buffer, length);
1063  }
1064  return X400_E_NOERROR;
1065 }
1066 
1067 static void print_sec_label(
1068  unsigned char slab_buffer[],
1069  unsigned int length
1070 )
1071 {
1072 
1073  char xml_buffer[XML_BUFSIZE];
1074  int status;
1075 
1076  status = SecLabelInit("Example program");
1077  if (status != SECLABEL_E_NOERROR) {
1078  fprintf(stderr, "SecLabelInit returned error %d\n", status);
1079  return ;
1080  }
1081 
1082  status = SecLabelPrint(slab_buffer,
1083  length,
1084  xml_buffer,
1085  XML_BUFSIZE);
1086 
1087  if (status != SECLABEL_E_NOERROR) {
1088  fprintf(stderr, "SecLabelParse returned error %d\n", status);
1089  return ;
1090  }
1091 
1092  /* You could now write out the XML file, or parse it in memory..*/
1093  printf("Got security label:%s\n", xml_buffer);
1094  return;
1095 }
1096 
1097 static int get_cic(
1098  struct X400Recipient *rp
1099 )
1100 {
1101  char buffer[BUFSIZ];
1102  int status, cic_status;
1103  int intparam;
1104  size_t length;
1105 
1106  /* get back status of the Content Integrity Check in the recipient */
1108  &intparam);
1109  if (cic_status == X400_E_NO_VALUE) {
1110  printf("No Content Integrity Check in recipient\n");
1111  return X400_E_NOERROR;
1112  } else if (cic_status != X400_E_NOERROR) {
1113  printf("Error from RecipGetIntParam: %s\n", X400msError(cic_status));
1114  return cic_status;
1115  }
1116 
1117  /* report CIC information */
1118  switch (intparam) {
1119  case X400_E_NOERROR:
1120  printf("Content Integrity Check succeeded\n");
1121  break;
1122  default:
1123  printf("Content Integrity Check error (%d): %s\n",
1124  intparam, X400msError(intparam));
1125  break;
1126  }
1127 
1128  /* Return the Content Integrity Check */
1130  buffer, sizeof buffer, &length);
1131  if (status != X400_E_NOERROR) {
1132  fprintf(stderr, "Error getting recipient cic: %s\n",
1133  X400msError(status));
1134  } else {
1135  printf("Content Integrity Check found in recipient (%d)\n",
1136  (int)length);
1137  }
1138 
1139  show_certificate (rp, X400_N_CERT_RECIP_CIC, "recipient CIC");
1140 
1141  return X400_E_NOERROR;
1142 }
1143 
1144 static void show_certificate (
1145  struct X400Recipient *rp,
1146  int certtype,
1147  const char *tag)
1148 {
1149  int status;
1150  struct X400Certificate *cert;
1151  char buffer[BUFSIZ];
1152  size_t length;
1153  int paramval;
1154 
1155  status = X400RecipGetCert (rp, certtype, &cert);
1156  if ( status != X400_E_NOERROR ) {
1157  fprintf (stderr, "Error getting %s certificate: %s\n",
1158  tag, X400msError (status));
1159  return;
1160  }
1161 
1162  /* Return the subject DN from Orig cert */
1164  buffer, sizeof buffer, &length);
1165  if (status != X400_E_NOERROR) {
1166  fprintf(stderr, "Error getting subject of cert used for %s: %s\n",
1167  tag, X400msError(status));
1168  } else {
1169  printf("Subject of Cert used to verify %s (%.*s)\n",
1170  tag, (int)length, buffer);
1171  }
1172 
1173  /* Return the issuer DN from Orig cert */
1175  buffer, sizeof buffer, &length);
1176  if (status != X400_E_NOERROR) {
1177  fprintf(stderr, "Error getting issuer of cert used for %s: %s\n",
1178  tag, X400msError(status));
1179  } else {
1180  printf("Issuer of Cert used to verify %s (%.*s)\n",
1181  tag, (int)length, buffer);
1182  }
1183 
1184  /* Return the serial number from Orig cert used to verify the
1185  * Content Integrity Check */
1187  buffer, sizeof buffer, &length);
1188  if (status != X400_E_NOERROR) {
1189  fprintf(stderr, "Error getting serial num of cert used for %s: %s\n",
1190  tag, X400msError(status));
1191  } else {
1192  printf("Serial Num of Cert used to verify %s (%.*s)\n",
1193  tag, (int)length, buffer);
1194  }
1195 
1196  /* Return the Orig cert used to verify the Content Integrity Check */
1197  status = X400CertGetStrParam(cert, X400_S_CERT_BER,
1198  buffer, sizeof buffer, &length);
1199  if (status != X400_E_NOERROR) {
1200  fprintf(stderr, "Error getting cert der used for %s: %s\n",
1201  tag, X400msError(status));
1202  } else {
1203  printf(
1204  "Returned Cert used to verify %s (%d)\n",
1205  tag, (int)length);
1206  }
1207 
1208  /* Find any ORaddress subject alt name and its status */
1209  status = X400CertGetStrParam(cert, X400_S_OR_ADDRESS,
1210  buffer, sizeof buffer, &length);
1211  if (status != X400_E_NOERROR) {
1212  if ( status == X400_E_NO_VALUE ) {
1213  fprintf(stderr, "No ORaddress subject alt. name\n");
1214  } else {
1215  fprintf(stderr, "Error from CertGetStrParam: %s\n",
1216  X400msError(status));
1217  return;
1218  }
1219  } else {
1220  fprintf(stderr, "ORaddress subject alt name: '%.*s'\n",
1221  (int)length, buffer);
1222  }
1223 
1224  status = X400CertGetIntParam(cert, X400_N_CERT_ORADDRESS_STATUS, &paramval);
1225 
1226  if (status != X400_E_NOERROR) {
1227  fprintf(stderr, "Error from CertGetStrParam: %s\n",
1228  X400msError(status));
1229  return;
1230  }
1231 
1232  fprintf(stderr, "ORaddress subject alt name status: %s\n",
1233  X400msError (paramval));
1234 }
1235 
1236 static void usage(void) {
1237  printf("usage: %s\n", optstr);
1238  printf("\t where:\n");
1239  printf("\t -u : Don't prompt to override defaults \n");
1240  printf("\t -3 : Use P3 connection \n");
1241  printf("\t -7 : Use P7 connection \n");
1242  printf("\t -m : OR Address in P7 bind arg \n");
1243  printf("\t -d : DN in P7 bind arg \n");
1244  printf("\t -p : Presentation Address of P7 Store \n");
1245  printf("\t -w : P7 password of P7 user \n");
1246  printf("\t -M : OR Address in P3 bind arg \n");
1247  printf("\t -D : DN in P3 bind arg \n");
1248  printf("\t -P : Presentation Address of P3 server\n");
1249  printf("\t -W : P3 password of P3 user \n");
1250  printf("\t -e : Security Environment (dir with x509 subdir): obsolete, use -Y <p12file>\n");
1251  printf("\t -x : DN of X.509 Digital Identity\n");
1252  printf("\t -b : Passphrase for private key in PKCS12 file\n");
1253  printf("\t -E : Fetch messages until all read\n");
1254  printf("\t -Y : Filename of PKCS12 file containing Digital Identity\n");
1255  printf("\t -U : Directory containing trust anchors\n");
1256  printf("\t -I : Generate IPN from message received\n");
1257  return;
1258 }
#define X400_MSG_MESSAGE
Definition: x400_att.h:29
#define X400_S_CERT_SERIAL_NUM
Definition: x400_att.h:1522
#define X400_S_MSGTOK_RECIP
Definition: x400_att.h:1436
#define X400_N_NON_RECEIPT_REASON
Definition: x400_att.h:1013
#define X400_S_LOG_CONFIGURATION_FILE
Definition: x400_att.h:1091
int X400msSetStrDefault(struct X400msSession *sp, int paramtype, const char *value, size_t length)
Set a default string parameter value in a session.
#define X400_N_MSGTOK_SEC_LAB_STATUS
Definition: x400_att.h:1445
#define X400_S_CERT_SUBJECT_DN
Definition: x400_att.h:1516
#define X400_S_SUBJECT_IDENTIFIER
Definition: x400_att.h:1038
#define X400_N_CONTENT_LENGTH
Definition: x400_att.h:411
int X400msMsgGetIntParam(struct X400msMessage *mp, int paramtype, int *valp)
Return a integer-valued parameter from the message object.
#define X400_E_X509_ENV
Definition: x400_att.h:175
#define X400_S_SEC_IDENTITY
Definition: x400_att.h:554
#define X400_E_X509_CERT_INVALID
Definition: x400_att.h:199
#define X400_N_MSGTOK_RECIP_STATUS
Definition: x400_att.h:1448
int X400msMsgGet(struct X400msSession *sp, int number, struct X400msMessage **mpp, int *typep, int *seqp)
Get message object for transfer out from MS or MTA via P3.
#define X400_S_MSGTOK_CIC
Definition: x400_att.h:1454
#define X400_N_MSGTOK_STATUS
Definition: x400_att.h:1427
#define X400_N_PRECEDENCE
Definition: x400_att.h:685
#define X400_S_SUPPLEMENTARY_INFO
Definition: x400_att.h:1041
const char * X400msError(int error)
Obtain a string describing the meaning of the given error code.
#define X400_E_X509_VERIFY_FAIL_NO_CERT
Definition: x400_att.h:184
#define X400_E_NO_RECIP
Definition: x400_att.h:109
int X400msMsgNew(struct X400msSession *sp, int type, struct X400msMessage **mpp)
Creates new message.
int X400msClose(struct X400msSession *sp)
Close a X400 Session.
#define X400_S_MSGTOK_SEC_LAB
Definition: x400_att.h:1439
int X400msMakeIPN(struct X400msMessage *mp, int non_receipt_reason, struct X400msMessage **mpp)
Make an IPN based on the subject IPM.
#define X400_E_NO_VALUE
Definition: x400_att.h:100
#define X400_N_PROOF_OF_DEL_REQ
Definition: x400_att.h:977
int X400msRecipGet(struct X400msMessage *mp, int type, int number, struct X400Recipient **rpp)
Get recipient object from message.
#define X400_T_IA5TEXT
Definition: x400_att.h:798
#define X400_E_NOERROR
Definition: x400_att.h:46
int X400msOpen(int type, const char *oraddr, const char *dirname, const char *credentials, const char *pa, int *messages, struct X400msSession **spp)
Open a session to a Message Store (P7) or MTA (P3) in synchronous mode.
#define X400_N_CERT_ORADDRESS_STATUS
Definition: x400_att.h:1525
#define X400_S_OR_ADDRESS
Definition: x400_att.h:349
#define X400_N_CONTENT_TYPE
Definition: x400_att.h:408
#define X400_S_SUBJECT_IPM
Definition: x400_att.h:1007
#define X400_S_MSGTOK_DER
Definition: x400_att.h:1430
#define X400_S_SEC_IDENTITY_PASSPHRASE
Definition: x400_att.h:560
#define X400_S_SUPP_RECEIPT_INFO
Definition: x400_att.h:1030
#define X400_S_MESSAGE_IDENTIFIER
Definition: x400_att.h:405
int X400msMsgGetStrParam(struct X400msMessage *mp, int paramtype, char *buffer, size_t buflen, size_t *paramlenp)
Return a string-valued parameter from the message object.
#define X400_E_X509_VERIFY_FAIL
Definition: x400_att.h:196
#define X400_N_CERT_RECIP_CIC
Definition: x400_att.h:1500
int X400msRecipGetIntParam(struct X400Recipient *rp, int paramtype, int *valp)
Return a integer-valued parameter from the recipient object.
#define X400_S_SECURITY_LABEL
Definition: x400_att.h:1338
#define X400_RECIP_PRIMARY
Definition: x400_att.h:296
#define X400_N_DISCARD_REASON
Definition: x400_att.h:1016
int X400CertGetIntParam(struct X400Certificate *cp, int paramtype, int *valp)
Return a integer-valued parameter from the certificate object.
#define X400_S_SEC_IDENTITY_DN
Definition: x400_att.h:563
#define X400_S_CERT_BER
Definition: x400_att.h:1513
#define X400_E_X509_VERIFY_FAIL_UNSUPPORTED_ALG
Definition: x400_att.h:193
#define X400_N_RECIP_CIC_STATUS
Definition: x400_att.h:1465
int X400msMsgSend(struct X400msMessage *mp)
Send message object.
#define X400_E_X509_VERIFY_FAIL_INCOMPAT_ALG
Definition: x400_att.h:190
int X400msRecipGetStrParam(struct X400Recipient *rp, int paramtype, char *buffer, size_t buflen, size_t *paramlenp)
Return a string-valued parameter from the recipient object.
#define X400_N_NON_DELIVERY_REASON
Definition: x400_att.h:1050
#define X400_B_RETURN_VERIFICATION_ERRORS
Definition: x400_att.h:1098
X400 MA/MS (P3/P7) Interface.
#define X400_S_CERT_ISSUER_DN
Definition: x400_att.h:1519
#define X400_N_CERT_MSGTOK
Definition: x400_att.h:1497
#define X400_N_MSGTOK_SEQ_NUM
Definition: x400_att.h:1433
#define X400_N_ACK_MODE
Definition: x400_att.h:1027
int X400msSetIntDefault(struct X400msSession *sp, int paramtype, int value)
Set a default integer parameter value in a session.
#define X400_E_X509_ITEM_INVALID
Definition: x400_att.h:202
#define X400_E_X509_INIT
Definition: x400_att.h:181
#define X400_S_SUBJECT
Definition: x400_att.h:722
int X400msWait(struct X400msSession *sp, int seconds, int *count)
Wait for messages to be ready to be read.
#define X400_RECIP_ENVELOPE
Definition: x400_att.h:335
#define X400_S_CONVERSION_EITS
Definition: x400_att.h:1010
#define X400_S_SEC_TRUSTED_CERTS_DIR
Definition: x400_att.h:581
#define X400_S_RECIP_CIC
Definition: x400_att.h:1468
#define X400_N_NON_DELIVERY_DIAGNOSTIC
Definition: x400_att.h:1053
#define X400_N_MSGTOK_PODR_STATUS
Definition: x400_att.h:1442
int X400RecipGetCert(struct X400Recipient *rp, int certtype, struct X400Certificate **certp)
Get certificate object from recipient This returns a certificate which was used to sign an object in ...
#define X400_N_IS_IPN
Definition: x400_att.h:1004
#define X400_N_MSGTOK_CIC_STATUS
Definition: x400_att.h:1451
#define X400_S_AUTOFORWARD_COMMENT
Definition: x400_att.h:1021
#define X400_RECIP_REPORT
Definition: x400_att.h:314
int X400msMsgDelete(struct X400msMessage *mp, int retain)
Delete message object.
#define X400_N_CERT_MSGTOK_CIC
Definition: x400_att.h:1503
int X400CertGetStrParam(struct X400Certificate *cp, int paramtype, char *buffer, size_t buflen, size_t *paramlenp)
Return a string-valued parameter from the certificate object.
#define X400_S_RECEIPT_TIME
Definition: x400_att.h:1024
#define X400_E_X509_VERIFY_FAIL_NO_PUBKEY
Definition: x400_att.h:187
int X400RecipGetStrParam(struct X400Recipient *rp, int paramtype, char *buffer, size_t buflen, size_t *paramlenp)
Return a string-valued parameter from the recipient object.
#define X400_S_MESSAGE_DELIVERY_TIME
Definition: x400_att.h:442