x400_msrcv_sign.c
1 /* Copyright (c) 2003-2013, 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  * Simple example program for receiving a message from a store.
15  * The security environment is set up so that signed messages
16  * will have the MOAC verified.
17  *
18  * Note that a valid Digital Identity is no longer required in order to
19  * perform verification. Instead the name of a directory containing trusted,
20  * self signed certificates in DER form can be passed in.
21  */
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <x400_msapi.h>
26 #include <seclabel_api.h> /* For security labels */
27 #include "example.h"
28 #include "ms_example.h"
29 
30 int num_unsigned_rcvd;
31 int num_unverified_rcvd;
32 int num_verified_rcvd;
33 
34 static char *optstr = "u37m:d:p:w:M:D:P:W:e:b:x:Y:U:";
35 
36 static void usage(void);
37 
38 
39 static int get_msg(
40  struct X400msSession *sp
41 );
42 
43 static void setup_default_new_sec_env(
44  struct X400msSession *sp,
45  char *sec_trusted_cert_dir
46 );
47 
48 static void setup_default_old_sec_env(
49  struct X400msSession *sp,
50  char *id,
51  char *dn,
52  char *pw /* passphrase for private key in pkcs12 file */
53 );
54 
55 static int report_moac_info(
56  struct X400msMessage *mp
57 );
58 
59 static void show_4406_certificate (struct X400msMessage *mp);
60 static void show_certificate (struct X400msMessage *mp);
61 static int report_4406_info(
62  struct X400msMessage *mp
63 );
64 
65 static void print_sec_label(
66  char slab_buffer[],
67  unsigned int length
68 );
69 
73 int
74 main(
75  int argc,
76  char **argv)
77 {
78  char buffer[BUFSIZ];
79  char pa[BUFSIZ];
80  char orn[BUFSIZ];
81  int status;
82  int nummsg;
83  struct X400msSession *sp;
84  int contype;
85  char *def_oraddr;
86  char *def_dn;
87  char *def_pa;
88 
89  if (get_args(argc, argv, optstr)) {
90  usage();
91  exit(-1);
92  }
93 
94  printf("Connection type (0 = P7, 1 = P3 submit only, 2 = P3 both directions) [%d]: ", x400_contype);
95  contype = ic_fgetc(x400_contype, stdin);
96  if (contype != 10)
97  ic_fgetc(x400_contype, stdin);
98 
99  if ( contype < '0' || '2' < contype )
100  contype = x400_contype;
101  else
102  contype -= '0';
103 
104  if (contype == 0) {
105  def_oraddr = x400_ms_user_addr;
106  def_dn = x400_ms_user_dn;
107  def_pa = x400_ms_presentation_address;
108  }
109  else {
110  def_oraddr = x400_mta_user_addr;
111  def_dn = x400_mta_user_dn;
112  def_pa = x400_mta_presentation_address;
113  }
114 
115  printf("Your ORAddress [%s] > ", def_oraddr);
116  ic_fgets(orn, sizeof orn, stdin);
117 
118  if (orn[strlen(orn) - 1] == '\n')
119  orn[strlen(orn) - 1] = '\0';
120 
121  if (orn[0] == '\0')
122  strcpy(orn, def_oraddr);
123 
124  /* Prompt for password; note: reflected. */
125  printf("Password [%s]: ",
126  contype == 0 ? x400_p7_password : x400_p3_password);
127  if (ic_fgets(buffer, sizeof buffer, stdin) == NULL)
128  exit(1);
129 
130  if (buffer[strlen(buffer) - 1] == '\n')
131  buffer[strlen(buffer) - 1] = '\0';
132  if (buffer[0] == '\0')
133  strcpy(buffer, contype == 0 ? x400_p7_password : x400_p3_password);
134 
135  printf("Presentation Address [%s] > ", def_pa);
136  ic_fgets(pa, sizeof pa, stdin);
137 
138  if (pa[strlen(pa) - 1] == '\n')
139  pa[strlen(pa) - 1] = '\0';
140 
141  if (pa[0] == '\0')
142  strcpy(pa, def_pa);
143 
144  status = X400msOpen(contype, orn, def_dn, buffer, pa, &nummsg, &sp);
145  if (status != X400_E_NOERROR) {
146  fprintf(stderr, "Error in Open: %s\n", X400msError(status));
147  exit(status);
148  }
149 
150 #ifdef USING_ALERTS
151  /* If we register the alert auto-action, we will get an alert indication
152  when a message is delivered. So there is no need to poll at
153  short intervals within X400ms_Wait - we can do a slow background
154  poll and rely on the Alert indication to wake the code up instead */
156 #endif
157 
158  /* setup logging from $(ETCDIR)x400api.xml or $(SHAREDIR)x400api.xml */
159  X400msSetStrDefault(sp, X400_S_LOG_CONFIGURATION_FILE, "x400api.xml", 0);
160 
161  if (contype == 0) {
162 #ifdef WANT_AUTOFORWARDING
163  struct X400msAutoActionParameter *aa_param;
164 
165  /* Register an Autoforwarding Autoaction. */
166  aa_param = X400msNewAutoActionParameter();
167 
168  /* Add mandatory things to AutoAction parameter for auto-forwarding:
169  i.e. recipient address */
170  X400RecipNew(0, &rp);
171 
172  X400RecipAddStrParam(rp, X400_S_OR_ADDRESS, def_oraddr,
173  strlen(def_oraddr));
174 
176 
179  "AF contentid", -1);
180 
182 
185  1);
186 
189  1);
190 
193  1);
194 
196 
199  "This message was autoforwarded",
200  -1);
201 
204  "This is a cover note", -1);
205 
208  "AutoForwarded:", -1);
209 
211  4, aa_param);
212  if (status != X400_E_NOERROR) {
213  fprintf(stderr,
214  "Error in RegisterAutoAction: %s\n", X400msError(status));
215  /* tidily close the session */
216  status = X400msClose(sp);
217  exit(status);
218  }
219  printf("Registered AutoForwarding autoaction (id = 4) OK\n");
221 #endif
222 
223 #ifdef USING_ALERTS
224  /* No parameter needed for Alert autoaction - we do not support
225  configuration of requested-attributes in this API yet. */
226  status = X400msRegisterAutoAction(sp, X400_AUTO_ALERT, 9, NULL);
227  if (status != X400_E_NOERROR) {
228  fprintf(stderr, "Error in RegisterAutoAction: %s\n",
229  X400msError(status));
230  /* tidily close the session */
231  status = X400msClose(sp);
232  exit(status);
233  }
234  printf("Registered AutoAlert autoaction (id = 9) OK\n");
235 #endif
236 
237  /* Just test the register and deregister functions */
238  status = X400msRegisterAutoAction(sp, X400_AUTO_ALERT, 10, NULL);
239  if (status != X400_E_NOERROR) {
240  fprintf(stderr, "Error in RegisterAutoAction: %s\n",
241  X400msError(status));
242  /* tidily close the session */
243  status = X400msClose(sp);
244  exit(status);
245  }
246  printf("Registered AutoAlert autoaction (id = 10) OK\n");
247 
248  /* Lets do a deregistration of the action we just registered */
250  if (status != X400_E_NOERROR) {
251  fprintf(stderr, "Error in DeregisterAutoAction: %s\n",
252  X400msError(status));
253  /* tidily close the session */
254  status = X400msClose(sp);
255  exit(status);
256  }
257  printf("Deregistered AutoAlert autoaction (id = 10) OK\n");
258  }
259 
260  if (nummsg == 0) {
261  printf ("no messages - waiting 60 seconds for a message to be delivered.....\n");
262  }
263  else {
264  printf("%d messages waiting\n", nummsg);
265  }
266 
267  status = get_msg(sp);
268  if (status != X400_E_NOERROR) {
269  fprintf(stderr, "Error in getting msg: %s\n",
270  X400msError(status));
271  exit(status);
272  }
273  fprintf(stderr, "got first\n");
274  status = get_msg(sp);
275  if (status != X400_E_NOERROR) {
276  fprintf(stderr, "Error in getting msg: %s\n",
277  X400msError(status));
278  exit(status);
279  }
280  fprintf(stderr, "got second\n");
281 
282  status = get_msg(sp);
283  if (status != X400_E_NOERROR) {
284  fprintf(stderr, "Error in getting msg: %s\n",
285  X400msError(status));
286  exit(status);
287  }
288  fprintf(stderr, "got third\n");
289 
290  status = get_msg(sp);
291  if (status != X400_E_NOERROR) {
292  fprintf(stderr, "Error in getting msg: %s\n",
293  X400msError(status));
294  exit(status);
295  }
296  fprintf(stderr, "got third\n");
297 
298  status = get_msg(sp);
299  if (status != X400_E_NOERROR) {
300  fprintf(stderr, "Error in getting msg: %s\n",
301  X400msError(status));
302  exit(status);
303  }
304  fprintf(stderr, "got third\n");
305 
306  status = get_msg(sp);
307  if (status != X400_E_NOERROR) {
308  fprintf(stderr, "Error in getting msg: %s\n",
309  X400msError(status));
310  exit(status);
311  }
312  fprintf(stderr, "got third\n");
313 
314  status = X400msClose(sp);
315  printf("%d num_unsigned_rcvd\n", num_unsigned_rcvd);
316  printf("%d num_unverified_rcvd\n", num_unverified_rcvd);
317  printf("%d num_verified_rcvd\n", num_verified_rcvd);
318  return(status);
319 }
320 
321 
322 static int get_msg(
323  struct X400msSession *sp
324 )
325 {
326  char buffer[BUFSIZ];
327  int status, sig_status;
328  int nummsg;
329  int type;
330  int seqn;
331  struct X400msMessage *mp;
332  struct X400Recipient *rp;
333  int n;
334  size_t length;
335  int intparam;
336  char recipient_str[BUFSIZ];
337 
338  printf("Waiting for new messages for 10 seconds\n");
339  status = X400msWait(sp, 10, &nummsg);
340  if (status != X400_E_NOERROR) {
341  fprintf(stderr, "Error from Wait: %s\n", X400msError(status));
342  /* tidily close the session */
343  status = X400msClose(sp);
344  exit(status);
345  }
346  printf("------------- New Message ----------------\n");
347 
348  /* Set up the security environment.
349  *
350  * In R15.0 this need only be the name of a trusted certificate directory.
351  *
352  * Prior to R15.0, the ID is specified as a pathname, in which the
353  * subdirectory "x509" is expected to contain one or more PKCS12
354  * files. The appropriate Digital Identity is determined from the
355  * DN of the subject, and the passphrase is used to decrypt the
356  * private key. NB even though we're not going to use our cert,
357  * (as we're going to use the cert in the message to check the MOAC
358  * we need to do this due to a limitation in the underlying X.509
359  * layer.
360  */
361  if (use_new_sec_env) {
362  setup_default_new_sec_env(sp, trusted_ca_certs_dir);
363  } else {
364  setup_default_old_sec_env(sp, security_id, identity_dn, passphrase);
365  }
366 
367 
368  /* Turn off legacy bahaviour in which MOAC verification failure
369  * returns X400_E_NOERROR.
370  * We will now get X400_E_X509_VERIFY_FAILURE from MsgGet
371  * if/when the verification fails
372  */
374 
375  if (x400_default_recipient != NULL)
376  printf("Getting message\n");
377  status = X400msMsgGet(sp, 0, &mp, &type, &seqn);
378  switch (status) {
379  case X400_E_NOERROR:
380  fprintf(stderr, "MsgGet successfully got message\n");
381  break;
382  default :
383  fprintf(stderr, "Error from MsgGet: %s\n", X400msError(status));
384  /* tidily close the session */
385  status = X400msClose(sp);
386  exit(status);
387  break;
388  }
389 
390  if (type != X400_MSG_MESSAGE) {
391  fprintf(stderr, "Got a report (printing only some attributes)\n");
392 
393  /* The ORADDRESS in the message is the (envelope) originator */
395  buffer, sizeof buffer, &length);
396  if (status != X400_E_NOERROR) {
397  fprintf(stderr, "Error from MsgGetStrParam: %s\n",
398  X400msError(status));
399  /* tidily close the session */
400  status = X400msClose(sp);
401  exit(status);
402  }
403  printf("Subject Identifier: %.*s\n", (int)length, buffer);
404 
405  /* Get the primary recipients */
406  for (n = 1;; n++) {
407  status = X400msRecipGet(mp, X400_RECIP_REPORT, n, &rp);
408  if (status == X400_E_NO_RECIP)
409  break;
410  if (status != X400_E_NOERROR) {
411  fprintf(stderr, "Error from RecipGet: %s\n",
412  X400msError(status));
413  /* tidily close the session */
414  status = X400msClose(sp);
415  exit(status);
416  }
417 
418  /* Note: recipient may not actually have an O/R address */
420  recipient_str,
421  sizeof recipient_str, &length);
422  if (status != X400_E_NOERROR) {
423  fprintf(stderr, "Error from RecipGetStrParam: %s\n",
424  X400msError(status));
425  /* tidily close the session */
426  status = X400msClose(sp);
427  exit(status);
428  }
429  /* print out the O/R Address of the report */
430  printf("Positive Delivery Report for recipient %d: %.*s\n", n,
431  (int)length, recipient_str);
432 
433  /* The original message delivery time, if this attribute exists,
434  * then the report is a positive Delivery Report */
436  buffer, sizeof buffer, &length);
437  if (status == X400_E_NOERROR) {
438  /* Positive Delivery Report */
439  printf("Delivery Time: %.*s\n", (int)length, buffer);
440  }
441  else {
442  /* Negative Delivery Report */
443  printf("Negative Delivery Report for recipient %d: %s\n", n,
444  recipient_str);
445 
446  /* Supplementary Info to the report */
448  buffer, sizeof buffer,
449  &length);
450  if (status != X400_E_NOERROR) {
451  fprintf(stderr, "Error from RecipGetStrParam: %s\n",
452  X400msError(status));
453  buffer[0] = '\0';
454  }
455  printf("Supplementary Info: %.*s\n", (int)length, buffer);
456 
457  /* The reason why the message was not delivered */
458  status =
460  &intparam);
461  if (status != X400_E_NOERROR) {
462  fprintf(stderr, "Error from MsgGetIntParam: %s\n",
463  X400msError(status));
464  }
465  printf("Non-Delivery Reason: %d\n", intparam);
466 
467  /* The diagnostics of the report for this recipient */
468  status =
470  &intparam);
471  if (status != X400_E_NOERROR) {
472  fprintf(stderr, "Error from MsgGetIntParam: %s\n",
473  X400msError(status));
474  }
475  printf("Non-Delivery Diagnostic: %d\n", intparam);
476  }
477  }
478 
479  num_unsigned_rcvd++ ;
480  status = X400msMsgDelete(mp, 0);
481  if (status != X400_E_NOERROR) {
482  fprintf(stderr, "Error from X400msMsgDelete: %s\n",
483  X400msError(status));
484  }
485  return (status);
486  }
487 
488  /* report information about the MOAC in the message */
489  (void) report_moac_info(mp);
490 
491  /* report information about the 4406 in the message */
492  sig_status = report_4406_info(mp);
493 
494  /* X.411 security label */
496  buffer, sizeof buffer, &length);
497  if (status == X400_E_NOERROR) {
498  printf("X.411 Security Label returned OK (%d chars)\n", (int)length);
499  print_sec_label(buffer, length);
500  } else {
501  printf("X.411 Security Label not returned (%d) (%s)\n", status,
502  X400msError(status));
503  }
504 
505  /* content type */
506  status = X400msMsgGetIntParam(mp, X400_N_CONTENT_TYPE, &intparam);
507  if (status == X400_E_NOERROR) {
508  printf ("Content type : P%d\n", intparam);
509  } else {
510  fprintf(stderr, "No content type: Error from MsgGetStrParam: %s\n",
511  X400msError(status));
512  }
513 
514  /* external content type */
516  buffer, sizeof buffer, &length);
517  if (status == X400_E_NOERROR) {
518  printf("External Content Type: %.*s\n", (int)length, buffer);
519  } else {
520  fprintf(stderr, "No content type: Error from MsgGetStrParam: %s\n",
521  X400msError(status));
522  }
523 
524 
525  /* The message identifier */
527  buffer, sizeof buffer, &length);
528  if (status != X400_E_NOERROR) {
529  fprintf(stderr, "Error from MsgGetStrParam: %s\n",
530  X400msError(status));
531  /* tidily close the session */
532  status = X400msClose(sp);
533  exit(status);
534  }
535  printf("Message Identifier: %.*s\n", (int)length, buffer);
536 
537  /* The ORADDRESS in the message is the (envelope) originator */
539  buffer, sizeof buffer, &length);
540  if (status != X400_E_NOERROR) {
541  fprintf(stderr, "Error from MsgGetStrParam: %s\n",
542  X400msError(status));
543  /* tidily close the session */
544  status = X400msClose(sp);
545  exit(status);
546  }
547  printf("Originator: %.*s\n", (int)length, buffer);
548 
549  if (sig_status == X400_E_S4406_TRIPLE_WRAPPED) {
550  /* can't do much more with an encrypted message ... */
551  printf("Deleting triple wrapped message\n");
552 
553  /* Deletes message in message store as well as internal copy */
554  status = X400msMsgDelete(mp, 0);
555  return status;
556  }
557 
558  /* Get the primary recipients */
559  for (n = 1;; n++) {
560  status = X400msRecipGet(mp, X400_RECIP_PRIMARY, n, &rp);
561  if (status == X400_E_NO_RECIP)
562  break;
563  if (status != X400_E_NOERROR) {
564  fprintf(stderr, "Error from RecipGet: %s\n", X400msError(status));
565  /* tidily close the session */
566  status = X400msClose(sp);
567  exit(status);
568  }
569 
570  /* Note: recipient may not actually have an O/R address */
572  buffer, sizeof buffer, &length);
573  if (status == X400_E_NOERROR) {
574  printf("Recipient %d: %.*s\n", n, (int)length, buffer);
575  }
576 
577  status = X400msRecipGetIntParam(rp, X400_N_PRECEDENCE, &intparam);
578  if (status == X400_E_NOERROR) {
579  printf("Primary Recipient Precedence %d\n", intparam);
580  } else {
581  fprintf(stderr, "Error from RecipGet: %s\n", X400msError(status));
582  }
583 
584  }
585 
586  /* Subject is optional */
588  buffer, sizeof buffer, &length);
589  if (status == X400_E_NOERROR)
590  printf("Subject: %.*s\n", (int)length, buffer);
591 
592  /* external content type */
594  buffer, sizeof buffer, &length);
595  if (status == X400_E_NOERROR)
596  printf("External Content Type: %.*s\n", (int)length, buffer);
597 
598  /* And message text (or it could be another type) */
600  buffer, sizeof buffer, &length);
601  if (status == X400_E_NOERROR) {
602  printf("\nIA5 Text:\n%.*s\n\n", (int)length, buffer);
603  } else {
604  fprintf (stderr, "No IA5 text in message");
605  fprintf (stderr, "X400msMsgGetStrParam returned error: %s\n",
606  X400msError (status));
607  }
608 
609  /* get all the attachments */
610  printf("Getting body parts\n");
611  get_body_parts(mp);
612 
613  /* Deletes message in message store as well as internal copy */
614  status = X400msMsgDelete(mp, 0);
615 
616  return status;
617 }
618 
619 /*
620  * Recommended function to setup security env for verification.
621  * No digitial ID required - just a directory which contains
622  * trust anchors which are read as DER file (certificate.crt).
623  *
624  * The certificate (containing public key) is obtained from the message
625  * which is referenced in the message.
626  */
627 
628 static void setup_default_new_sec_env(
629  struct X400msSession *sp,
630  char *trusted_ca_certs_directory
631 )
632 {
633  int status;
634 
635  /* Directory containing trusted CA Certificates */
636  printf("Adding %s as trusted CA cert dir\n", trusted_ca_certs_directory);
638  trusted_ca_certs_directory, -1);
639  if ( status != X400_E_NOERROR ) {
640  fprintf (stderr, "X400msSetStrDefault returned error: %s\n",
641  X400msError (status));
642  exit (status);
643  }
644 
645  return;
646 }
647 
648 /*
649  * Obsolete function to use to set up the security environment. This provides a
650  * directory in which PKCS12 files are checked to find one whose subject DN
651  * matches that of this client.
652  *
653  * Any self signed certificates found in the directory are treated as
654  * trusted.
655  */
656 
657 static void setup_default_old_sec_env(
658  struct X400msSession *sp,
659  char *id,
660  char *dn,
661  char *pw /* passphrase for private key in pkcs12 file */
662 )
663 {
664  int status;
665 
666  /* first set a default security identity. This passes in the name of a
667  * directory, which contains an x509 subdirectory in which all Identities
668  * are held */
669  /* X400msSetStrDefault(sp, X400_S_SEC_IDENTITY, "/var/isode/dsa-db/", -1);
670  * */
672 
673  /* select by DN which Identity is to be used (if there are several)
674  * Currently these must be PKCS12 files */
675  status = X400msSetStrDefault (sp, X400_S_SEC_IDENTITY_DN, dn, -1);
676  if ( status != X400_E_NOERROR ) {
677  fprintf (stderr, "X400msSetStrDefault returned error: %s\n",
678  X400msError (status));
679  exit (status);
680  }
681 
682  /* passphrase used to open the Identity */
684  if ( status != X400_E_NOERROR ) {
685  fprintf (stderr, "X400msSetStrDefault returned error: %s\n",
686  X400msError (status));
687  exit (status);
688  }
689  return;
690 }
691 
692 
693 static int report_moac_info(
694  struct X400msMessage *mp
695 )
696 {
697  int status;
698  int intparam;
699 
700  /* Check the MOAC */
701  status = X400msMsgGetIntParam(mp, X400_N_MOAC_STATUS, &intparam);
702  switch ( status ) {
703  case X400_E_NO_VALUE:
704  num_unverified_rcvd++ ;
705  fprintf (stderr, "No MOAC in message\n");
706  break;
707 
708  default:
709  num_unverified_rcvd++ ;
710  fprintf (stderr, "Unexpected error getting MOAC status: %s\n",
711  X400msError (status));
712  break;
713 
714  case X400_E_NOERROR:
715  fprintf (stderr, "Have MOAC in message (%d)\n", intparam);
716  switch (intparam) {
717  case X400_E_NOERROR:
718  fprintf(stderr,
719  "MsgGet successfully verified signature in message\n");
720  show_certificate (mp);
721  fprintf(stderr, "continuing ...\n");
722  num_verified_rcvd++ ;
723  break;
725  fprintf(stderr,
726  "MOAC validation cannot take place because the security environment is invalid (%d):\n",
727  intparam);
728  /* other values will not be available */
729  break;
730  case X400_E_X509_INIT:
731  case X400_E_X509_ENV:
732  fprintf(stderr,
733  "MOAC validation cannot take place because the security environment is invalid (%d):\n",
734  intparam);
735  /* other values will not be available */
736  break;
738  fprintf(stderr, "Verification Error from MsgGet: %s\n",
739  X400msError(intparam));
740  show_certificate (mp);
741  fprintf(stderr, "continuing ...\n");
742  num_unverified_rcvd++ ;
743  break;
745  fprintf(stderr, "Verification Error from MsgGet: %s\n",
746  X400msError(intparam));
747  fprintf(stderr, "continuing ...\n");
748  num_unverified_rcvd++ ;
749  break;
751  fprintf(stderr, "Verification Error from MsgGet: %s\n",
752  X400msError(intparam));
753  show_certificate (mp);
754  fprintf(stderr, "continuing ...\n");
755  num_unverified_rcvd++ ;
756  break;
758  fprintf(stderr, "Verification Error from MsgGet: %s\n",
759  X400msError(intparam));
760  show_certificate (mp);
761  fprintf(stderr, "continuing ...\n");
762  num_unverified_rcvd++ ;
763  break;
765  fprintf(stderr, "Verification Error from MsgGet: %s\n",
766  X400msError(intparam));
767  show_certificate (mp);
768  fprintf(stderr, "continuing ...\n");
769  num_unverified_rcvd++ ;
770  break;
772  fprintf(stderr, "Verification Error from MsgGet: %s\n",
773  X400msError(intparam));
774  show_certificate (mp);
775  fprintf(stderr, "continuing ...\n");
776  num_unverified_rcvd++ ;
777  break;
779  fprintf(stderr, "Verification Error from MsgGet: %s\n",
780  X400msError(intparam));
781  show_certificate (mp);
782  fprintf(stderr, "continuing ...\n");
783  num_unverified_rcvd++ ;
784  break;
785  default :
786  fprintf(stderr,
787  "Unexpected verification error from MsgGet(%d): %s\n",
788  intparam,
789  X400msError(intparam));
790  show_certificate (mp);
791  fprintf(stderr, "continuing ...\n");
792  num_unverified_rcvd++ ;
793  break;
794  }
795  }
796  return X400_E_NOERROR;
797 }
798 
799 
800 static int report_4406_info(
801  struct X400msMessage *mp
802 )
803 {
804  int status;
805  int intparam;
806  size_t length;
807  char buffer[BUFSIZ];
808 
809  /* Check the 4406 signatures */
810  status = X400msMsgGetIntParam(mp, X400_N_S4406_STATUS, &intparam);
811  switch ( status ) {
812  case X400_E_NO_VALUE:
813  num_unverified_rcvd++ ;
814  fprintf (stderr, "No 4406 signature in message\n");
815  return X400_E_NOERROR;
816 
817  default:
818  num_unverified_rcvd++ ;
819  fprintf (stderr, "Unexpected error getting 4406 signature status: %s\n",
820  X400msError (status));
821  break;
822 
823  case X400_E_NOERROR:
824  fprintf (stderr, "Have 4406 signature in message (%d)\n", intparam);
825  switch (intparam) {
826  case X400_E_NOERROR:
827  fprintf(stderr,
828  "MsgGet successfully verified signature in message\n");
829  show_4406_certificate (mp);
830  fprintf(stderr, "continuing ...\n");
831  num_verified_rcvd++ ;
832  break;
834  fprintf(stderr,
835  "4406 signature validation cannot take place because the security environment is invalid (%d):\n",
836  intparam);
837  /* other values will not be available */
838  break;
839  case X400_E_X509_INIT:
840  case X400_E_X509_ENV:
841  fprintf(stderr,
842  "4406 signature validation cannot take place because the security environment is invalid (%d):\n",
843  intparam);
844  /* other values will not be available */
845  break;
847  fprintf(stderr, "Verification Error from MsgGet: %s\n",
848  X400msError(intparam));
849  show_4406_certificate (mp);
850  fprintf(stderr, "continuing ...\n");
851  num_unverified_rcvd++ ;
852  break;
854  fprintf(stderr, "Verification Error from MsgGet: %s\n",
855  X400msError(intparam));
856  fprintf(stderr, "continuing ...\n");
857  num_unverified_rcvd++ ;
858  break;
860  fprintf(stderr, "Verification Error from MsgGet: %s\n",
861  X400msError(intparam));
862  show_4406_certificate (mp);
863  fprintf(stderr, "continuing ...\n");
864  num_unverified_rcvd++ ;
865  break;
867  fprintf(stderr, "Verification Error from MsgGet: %s\n",
868  X400msError(intparam));
869  show_4406_certificate (mp);
870  fprintf(stderr, "continuing ...\n");
871  num_unverified_rcvd++ ;
872  break;
874  fprintf(stderr, "Verification Error from MsgGet: %s\n",
875  X400msError(intparam));
876  show_4406_certificate (mp);
877  fprintf(stderr, "continuing ...\n");
878  num_unverified_rcvd++ ;
879  break;
881  fprintf(stderr, "Verification Error from MsgGet: %s\n",
882  X400msError(intparam));
883  show_4406_certificate (mp);
884  fprintf(stderr, "continuing ...\n");
885  num_unverified_rcvd++ ;
886  break;
888  fprintf(stderr, "Verification Error from MsgGet: %s\n",
889  X400msError(intparam));
890  show_4406_certificate (mp);
891  fprintf(stderr, "continuing ...\n");
892  num_unverified_rcvd++ ;
893  break;
895  fprintf(stderr, "Verification Error from MsgGet: %s\n",
896  X400msError(intparam));
897  show_certificate (mp);
898  fprintf(stderr, "continuing ...\n");
899  num_unverified_rcvd++ ;
901  default :
902  fprintf(stderr, "Unexpected verification error from MsgGet: %s\n",
903  X400msError(intparam));
904  show_4406_certificate (mp);
905  fprintf(stderr, "continuing ...\n");
906  num_unverified_rcvd++ ;
907  break;
908  }
909  }
910 
911  /* 4406 security label */
912  printf("------------- 4406 Info ----------------\n");
914  buffer, sizeof buffer, &length);
915  if (status == X400_E_NOERROR) {
916  printf("4406 Security Label returned OK (%d chars)\n", (int)length);
917  print_sec_label(buffer, length);
918  } else {
919  printf("4406 Security Label not returned (%d) (%s)\n", status,
920  X400msError(status));
921  }
922 
923  /* 4406 signing time */
925  buffer, sizeof buffer, &length);
926  if (status == X400_E_NOERROR)
927  printf("4406 signing time returned OK\n%.*s\n", (int)length, buffer);
928  else
929  printf("4406 signing time not returned (%d) (%s)\n", status,
930  X400msError(status));
931 
932  printf("------------ End 4406 Info -----------\n");
933  return X400_E_NOERROR;
934 }
935 
936 static void show_certificate (struct X400msMessage *mp)
937 {
938  int status;
939  struct X400Certificate *cert;
940  char buffer[BUFSIZ];
941  size_t length;
942  int paramval;
943 
944  status = X400msMsgGetCert (mp, X400_N_CERT_MOAC, &cert);
945  if ( status != X400_E_NOERROR ) {
946  fprintf (stderr, "Error getting MOAC certificate: %s\n",
947  X400msError (status));
948  return;
949  }
950 
952  buffer, sizeof buffer, &length);
953  if (status != X400_E_NOERROR) {
954  fprintf(stderr, "Error from CertGetStrParam: %s\n",
955  X400msError(status));
956  return;
957  }
958  fprintf(stderr,
959  "subject DN of originator certificate '%.*s'\n", (int)length, buffer);
961  buffer, sizeof buffer, &length);
962  if (status != X400_E_NOERROR) {
963  fprintf(stderr, "Error from CertGetStrParam: %s\n",
964  X400msError(status));
965  return;
966  }
967  fprintf(stderr,
968  "issuer DN of originator certificate '%.*s'\n", (int)length, buffer);
969 
970  status = X400CertGetStrParam(cert, X400_S_OR_ADDRESS,
971  buffer, sizeof buffer, &length);
972  if (status != X400_E_NOERROR) {
973  if ( status == X400_E_NO_VALUE ) {
974  fprintf(stderr, "No ORaddress subject alt. name\n");
975  } else {
976  fprintf(stderr, "Error from CertGetStrParam: %s\n",
977  X400msError(status));
978  return;
979  }
980  } else {
981  fprintf(stderr, "ORaddress subject alt name: '%.*s'\n", (int)length, buffer);
982  }
983 
984  status = X400CertGetIntParam(cert, X400_N_CERT_ORADDRESS_STATUS, &paramval);
985 
986  if (status != X400_E_NOERROR) {
987  fprintf(stderr, "Error from CertGetStrParam: %s\n",
988  X400msError(status));
989  return;
990  }
991 
992  fprintf(stderr, "ORaddress subject alt name status: %s\n",
993  X400msError (paramval));
994 }
995 
996 
997 static void show_4406_certificate (struct X400msMessage *mp)
998 {
999  int status;
1000  struct X400Certificate *cert;
1001  char buffer[BUFSIZ];
1002  size_t length;
1003  int paramval;
1004 
1005  status = X400msMsgGetCert (mp, X400_N_S4406_CERTIFICATE, &cert);
1006  if ( status != X400_E_NOERROR ) {
1007  fprintf (stderr, "Error getting 4406 certificate: %s\n",
1008  X400msError (status));
1009  return;
1010  }
1011 
1013  buffer, sizeof buffer, &length);
1014  if (status != X400_E_NOERROR) {
1015  fprintf(stderr, "Error from CertGetStrParam: %s\n",
1016  X400msError(status));
1017  return;
1018  }
1019  fprintf(stderr, "subject DN of originator certificate '%.*s'\n",
1020  (int)length, buffer);
1022  buffer, sizeof buffer, &length);
1023  if (status != X400_E_NOERROR) {
1024  fprintf(stderr, "Error from CertGetStrParam: %s\n",
1025  X400msError(status));
1026  return;
1027  }
1028  fprintf(stderr, "issuer DN of originator certificate '%.*s'\n",
1029  (int)length, buffer);
1030 
1031  status = X400CertGetStrParam(cert, X400_S_OR_ADDRESS,
1032  buffer, sizeof buffer, &length);
1033  if (status != X400_E_NOERROR) {
1034  if ( status == X400_E_NO_VALUE ) {
1035  fprintf(stderr, "No ORaddress subject alt. name\n");
1036  } else {
1037  fprintf(stderr, "Error from CertGetStrParam: %s\n",
1038  X400msError(status));
1039  return;
1040  }
1041  } else {
1042  fprintf(stderr, "ORaddress subject alt name: '%.*s'\n",
1043  (int)length, buffer);
1044  }
1045 
1046  status = X400CertGetIntParam(cert, X400_N_CERT_ORADDRESS_STATUS, &paramval);
1047 
1048  if (status != X400_E_NOERROR) {
1049  fprintf(stderr, "Error from CertGetStrParam: %s\n",
1050  X400msError(status));
1051  return;
1052  }
1053 
1054  fprintf(stderr, "ORaddress subject alt name status: %s\n",
1055  X400msError (paramval));
1056  return;
1057 }
1058 
1059 
1060 static void print_sec_label(
1061  char slab_buffer[],
1062  unsigned int length
1063 )
1064 {
1065 
1066 #define XML_BUFSIZE 1024
1067 
1068  char xml_buffer[XML_BUFSIZE];
1069  int status;
1070 
1071  status = SecLabelInit("Example program");
1072  if (status != SECLABEL_E_NOERROR) {
1073  fprintf(stderr, "SecLabelInit returned error %d\n", status);
1074  return ;
1075  }
1076 
1077  status = SecLabelPrint((const unsigned char *) slab_buffer,
1078  length,
1079  xml_buffer,
1080  XML_BUFSIZE);
1081 
1082  if (status != SECLABEL_E_NOERROR) {
1083  fprintf(stderr, "SecLabelParse returned error %d\n", status);
1084  return ;
1085  }
1086 
1087  /* You could now write out the XML file, or parse it in memory..*/
1088  printf("Got security label:\n%s\n", xml_buffer);
1089  return;
1090 }
1091 
1092 
1093 static void usage(void) {
1094  printf("usage: %s\n", optstr);
1095  printf("\t where:\n");
1096  printf("\t -u : Don't prompt to override defaults \n");
1097  printf("\t -3 : Use P3 connection \n");
1098  printf("\t -7 : Use P7 connection \n");
1099  printf("\t -m : OR Address in P7 bind arg \n");
1100  printf("\t -d : DN in P7 bind arg \n");
1101  printf("\t -p : Presentation Address of P7 Store \n");
1102  printf("\t -w : P7 password of P7 user \n");
1103  printf("\t -M : OR Address in P3 bind arg \n");
1104  printf("\t -D : DN in P3 bind arg \n");
1105  printf("\t -P : Presentation Address of P3 server\n");
1106  printf("\t -W : P3 password of P3 user \n");
1107  printf("\t -e : Security Environment (dir with x509 subdir): obsolete, use -Y <p12file>\n");
1108  printf("\t -x : DN of X.509 Digital Identity\n");
1109  printf("\t -b : Passphrase for private key in PKCS12 file\n");
1110  printf("\t -Y : Filename of PKCS12 file containing Digital Identity\n");
1111  return;
1112 }
#define X400_S_LOG_CONFIGURATION_FILE
Definition: x400_att.h:1092
#define X400_S_CERT_ISSUER_DN
Definition: x400_att.h:1529
#define X400_AUTO_ALERT
Definition: x400_att.h:1334
#define X400_N_DISCLOSURE
Definition: x400_att.h:427
#define X400_N_S4406_CERTIFICATE
Definition: x400_att.h:624
int X400msAutoActionParameterAddIntParam(struct X400msAutoActionParameter *aap, int paramtype, int value)
Add integer-valued parameter to the autoaction parameter.
int X400msAutoActionParameterAddRecip(struct X400msAutoActionParameter *aap, int reciptype, struct X400Recipient *recip)
Add a receipient to the autoaction parameter.
#define X400_N_CONTENT_RETURN_REQUEST
Definition: x400_att.h:436
#define X400_S_THIS_IPM_PREFIX
Definition: x400_att.h:1245
#define X400_E_SIGN_NO_IDENTITY
Definition: x400_att.h:205
#define X400_N_S4406_STATUS
Definition: x400_att.h:608
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_S_COVER_NOTE
Definition: x400_att.h:1242
struct X400msAutoActionParameter * X400msNewAutoActionParameter(void)
Create a new (empty) autoaction parameter structure.
#define X400_S_SEC_IDENTITY
Definition: x400_att.h:554
int X400msSetStrDefault(struct X400msSession *sp, int paramtype, const char *value, size_t length)
Set a default string parameter value in a session.
#define X400_E_X509_CERT_INVALID
Definition: x400_att.h:199
#define X400_E_X509_ENV
Definition: x400_att.h:175
int X400CertGetIntParam(struct X400Certificate *cp, int paramtype, int *valp)
Return a integer-valued parameter from the certificate object.
void X400msFreeAutoActionParameter(struct X400msAutoActionParameter *aa_param)
Free an autoaction parameter.
int X400msMsgGetCert(struct X400msMessage *mp, int certtype, struct X400Certificate **certp)
Get certificate object from message This returns a certificate which was used to sign an object in th...
#define X400_E_X509_VERIFY_FAIL_NO_CERT
Definition: x400_att.h:184
#define X400_E_X509_VERIFY_FAIL_NO_PUBKEY
Definition: x400_att.h:187
#define X400_E_NO_RECIP
Definition: x400_att.h:109
#define X400_S_SECURITY_LABEL
Definition: x400_att.h:1348
int X400msClose(struct X400msSession *sp)
Close a X400 Session.
#define X400_E_NO_VALUE
Definition: x400_att.h:100
int X400msDeregisterAutoAction(struct X400msSession *sp, int type, int id)
Deregister an autoaction from the Message Store.
int X400msRecipGetIntParam(struct X400Recipient *rp, int paramtype, int *valp)
Return a integer-valued parameter from the recipient object.
#define X400_S_S4406_SIGNING_TIME
Definition: x400_att.h:629
#define X400_S_S4406_SECURITY_LABEL
Definition: x400_att.h:619
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_N_PRIORITY
Definition: x400_att.h:422
int X400RecipAddStrParam(struct X400Recipient *rp, int paramtype, const char *value, size_t length)
Add string-valued parameter to the recipient.
#define X400_S_MESSAGE_DELIVERY_TIME
Definition: x400_att.h:442
#define X400_E_X509_ITEM_INVALID
Definition: x400_att.h:202
#define X400_E_S4406_TRIPLE_WRAPPED
Definition: x400_att.h:235
#define X400_AUTO_FORWARDING
Definition: x400_att.h:1337
int X400RecipNew(int type, struct X400Recipient **rpp)
Create a new recipient object.
const char * X400msError(int error)
Obtain a string describing the meaning of the given error code.
#define X400_T_IA5TEXT
Definition: x400_att.h:799
#define X400_N_CERT_MOAC
Definition: x400_att.h:1502
#define X400_S_SEC_IDENTITY_DN
Definition: x400_att.h:563
#define X400_RECIP_STANDARD
Definition: x400_att.h:341
#define X400_S_AUTO_FORWARDING_COMMENT
Definition: x400_att.h:1238
#define X400_S_CONTENT_IDENTIFIER
Definition: x400_att.h:414
int X400msWait(struct X400msSession *sp, int seconds, int *count)
Wait for messages to be ready to be read.
#define X400_S_MESSAGE_IDENTIFIER
Definition: x400_att.h:405
#define X400_S_SEC_IDENTITY_PASSPHRASE
Definition: x400_att.h:560
#define X400_N_WAIT_INTERVAL
Definition: x400_att.h:1085
#define X400_E_NOERROR
Definition: x400_att.h:46
#define X400_N_IMPLICIT_CONVERSION_PROHIBITED
Definition: x400_att.h:430
#define X400_N_MOAC_STATUS
Definition: x400_att.h:572
#define X400_S_SUBJECT_IDENTIFIER
Definition: x400_att.h:1039
int X400msRecipGet(struct X400msMessage *mp, int type, int number, struct X400Recipient **rpp)
Get recipient object from message.
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_S_EXTERNAL_CONTENT_TYPE
Definition: x400_att.h:447
X400 MA/MS (P3/P7) Interface.
#define X400_E_X509_VERIFY_FAIL_UNSUPPORTED_ALG
Definition: x400_att.h:193
#define X400_E_X509_VERIFY_FAIL
Definition: x400_att.h:196
int X400msAutoActionParameterAddStrParam(struct X400msAutoActionParameter *aap, int paramtype, const char *value, size_t length)
Add string-valued parameter to the autoaction parameter.
#define X400_N_CERT_ORADDRESS_STATUS
Definition: x400_att.h:1535
int X400msMsgGetIntParam(struct X400msMessage *mp, int paramtype, int *valp)
Return a integer-valued parameter from the message object.
#define X400_RECIP_PRIMARY
Definition: x400_att.h:296
#define X400_E_X509_VERIFY_FAIL_INCOMPAT_ALG
Definition: x400_att.h:190
int X400msSetIntDefault(struct X400msSession *sp, int paramtype, int value)
Set a default integer parameter value in a session.
#define X400_N_NON_DELIVERY_DIAGNOSTIC
Definition: x400_att.h:1054
#define X400_N_NON_DELIVERY_REASON
Definition: x400_att.h:1051
#define X400_S_SUBJECT
Definition: x400_att.h:723
#define X400_B_RETURN_VERIFICATION_ERRORS
Definition: x400_att.h:1099
#define X400_N_ALTERNATE_RECIPIENT_ALLOWED
Definition: x400_att.h:433
#define X400_S_CERT_SUBJECT_DN
Definition: x400_att.h:1526
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_S_SUPPLEMENTARY_INFO
Definition: x400_att.h:1042
#define X400_E_X509_INIT
Definition: x400_att.h:181
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_SEC_TRUSTED_CERTS_DIR
Definition: x400_att.h:581
int X400msRegisterAutoAction(struct X400msSession *sp, int type, int id, struct X400msAutoActionParameter *aa_param)
Register an autoaction with the Message Store.
#define X400_N_PRECEDENCE
Definition: x400_att.h:686
#define X400_MSG_MESSAGE
Definition: x400_att.h:29
#define X400_N_CONTENT_TYPE
Definition: x400_att.h:408
#define X400_S_OR_ADDRESS
Definition: x400_att.h:349
int X400msMsgDelete(struct X400msMessage *mp, int retain)
Delete message object.
#define X400_RECIP_REPORT
Definition: x400_att.h:314