Summary: Isode provides a number of APIs which allow integrators and product developers to build components that access the Isode Messaging server products or other products supporting the same protocols.
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 
40 static char *optstr = "u37m:d:p:w:M:D:P:W:e:b:x:EY:U:";
41 
42 static void usage(void);
43 
44 
45 static int get_msg(
46  struct X400msSession *sp
47 );
48 
49 static void setup_default_new_sec_env(
50  struct X400msSession *sp,
51  char *sec_trusted_cert_dir
52 );
53 
54 static void setup_default_old_sec_env(
55  struct X400msSession *sp,
56  char *id,
57  char *dn,
58  char *pw /* passphrase for private key in pkcs12 file */
59 );
60 
61 static void report_msg_token_info(
62  struct X400Recipient *rp
63 );
64 
65 static int get_sec_label(
66  struct X400msMessage *mp
67 );
68 
69 static void print_sec_label(
70  unsigned char slab_buffer[],
71  unsigned int length
72 );
73 
74 static int get_cic(
75  struct X400Recipient *rp
76 );
77 
78 static void show_certificate (
79  struct X400Recipient *rp,
80  int certtype,
81  const char *tag
82 );
83 
87 int
88 main(
89  int argc,
90  char **argv)
91 {
92  char buffer[BUFSIZ];
93  char pa[BUFSIZ];
94  char orn[BUFSIZ];
95  int status;
96  int nummsg;
97  struct X400msSession *sp;
98  int contype;
99  char *def_oraddr;
100  char *def_dn;
101  char *def_pa;
102 
103  if (get_args(argc, argv, optstr)) {
104  usage();
105  exit(-1);
106  }
107 
108  printf("Connection type (0 = P7, 1 = P3 submit only, 2 = P3 both directions) [%d]: ", x400_contype);
109  contype = ic_fgetc(x400_contype, stdin);
110  if (contype != 10)
111  ic_fgetc(x400_contype, stdin);
112 
113  if ( contype < '0' || '2' < contype )
114  contype = x400_contype;
115  else
116  contype -= '0';
117 
118  if (contype == 0) {
119  def_oraddr = x400_ms_user_addr;
120  def_dn = x400_ms_user_dn;
121  def_pa = x400_ms_presentation_address;
122  }
123  else {
124  def_oraddr = x400_mta_user_addr;
125  def_dn = x400_mta_user_dn;
126  def_pa = x400_mta_presentation_address;
127  }
128 
129  printf("Your ORAddress [%s] > ", def_oraddr);
130  ic_fgets(orn, sizeof orn, stdin);
131 
132  if (orn[strlen(orn) - 1] == '\n')
133  orn[strlen(orn) - 1] = '\0';
134 
135  if (orn[0] == '\0')
136  strcpy(orn, def_oraddr);
137 
138  /* Prompt for password; note: reflected. */
139  printf("Password [%s]: ",
140  contype == 0 ? x400_p7_password : x400_p3_password);
141  if (ic_fgets(buffer, sizeof buffer, stdin) == NULL)
142  exit(1);
143 
144  if (buffer[strlen(buffer) - 1] == '\n')
145  buffer[strlen(buffer) - 1] = '\0';
146  if (buffer[0] == '\0')
147  strcpy(buffer, contype == 0 ? x400_p7_password : x400_p3_password);
148 
149  printf("Presentation Address [%s] > ", def_pa);
150  ic_fgets(pa, sizeof pa, stdin);
151 
152  if (pa[strlen(pa) - 1] == '\n')
153  pa[strlen(pa) - 1] = '\0';
154 
155  if (pa[0] == '\0')
156  strcpy(pa, def_pa);
157 
158  status = X400msOpen(contype, orn, def_dn, buffer, pa, &nummsg, &sp);
159  if (status != X400_E_NOERROR) {
160  fprintf(stderr, "Error in Open: %s\n", X400msError(status));
161  exit(status);
162  }
163 
164  /* setup logging from $(ETCDIR)x400api.xml or $(SHAREDIR)x400api.xml */
165  X400msSetStrDefault(sp, X400_S_LOG_CONFIGURATION_FILE, "x400api.xml", 0);
166 
167  if (nummsg == 0) {
168  printf ("no messages - waiting for a message to be delivered.....\n");
169  }
170  else {
171  printf("%d messages waiting\n", nummsg);
172  }
173 
174  status = get_msg(sp);
175  if (status != X400_E_NOERROR) {
176  fprintf(stderr, "Error in getting msg: %s\n",
177  X400msError(status));
178  exit(status);
179  }
180  fprintf(stderr, "got first\n");
181 
182  do {
183  fprintf(stderr, "================================================\n");
184  status = get_msg(sp);
185  if (status != X400_E_NOERROR) {
186  fprintf(stderr, "Error in getting msg: %s\n",
187  X400msError(status));
188  exit(status);
189  }
190  } while (until_no_more_msgs);
191 
192  status = X400msClose(sp);
193  printf("%d num_messagese_rcvd\n", num_messages_rcvd);
194  printf("%d num_reports_rcvd\n", num_reports_rcvd);
195  printf("%d num_unsigned_rcvd\n", num_unsigned_rcvd);
196  printf("%d num_unverified_rcvd\n", num_unverified_rcvd);
197  printf("%d num_verified_rcvd\n", num_verified_rcvd);
198  return(status);
199 }
200 
201 
202 static int get_msg(
203  struct X400msSession *sp
204 )
205 {
206  char buffer[BUFSIZ];
207  int status;
208  int nummsg;
209  int type;
210  int seqn;
211  struct X400msMessage *mp;
212  struct X400Recipient *rp;
213  int n;
214  size_t length;
215  int intparam;
216  char recipient_str[BUFSIZ];
217 
218  printf("Waiting for new messages for 10 seconds\n");
219  status = X400msWait(sp, 10, &nummsg);
220  if (status != X400_E_NOERROR) {
221  fprintf(stderr, "Error from Wait: %s\n", X400msError(status));
222  /* tidily close the session */
223  status = X400msClose(sp);
224  printf("%d num_messagese_rcvd\n", num_messages_rcvd);
225  printf("%d num_reports_rcvd\n", num_reports_rcvd);
226  printf("%d num_unsigned_rcvd\n", num_unsigned_rcvd);
227  printf("%d num_unverified_rcvd\n", num_unverified_rcvd);
228  printf("%d num_verified_rcvd\n", num_verified_rcvd);
229  exit(status);
230  }
231 
232  /* Set up the security environment.
233  *
234  * In R15.0 this need only be the name of a trusted certificate directory.
235  *
236  * Prior to R15.0, the ID is specified as a pathname, in which the
237  * subdirectory "x509" is expected to contain one or more PKCS12
238  * files. The appropriate Digital Identity is determined from the
239  * DN of the subject, and the passphrase is used to decrypt the
240  * private key. NB even though we're not going to use our cert,
241  * (as we're going to use the cert in the message to check the MOAC
242  * we need to do this due to a limitation in the underlying X.509
243  * layer.
244  */
245  if (use_new_sec_env) {
246  setup_default_new_sec_env(sp, trusted_ca_certs_dir);
247  } else {
248  setup_default_old_sec_env(sp, security_id, identity_dn, passphrase);
249  }
250 
251  /* Turn off legacy bahaviour in which MOAC verification failure
252  * returns X400_E_NOERROR.
253  * We will now get X400_E_X509_VERIFY_FAILURE from MsgGet
254  * if/when the verification fails
255  */
257 
258  printf("Getting message\n");
259 
260  status = X400msMsgGet(sp, 0, &mp, &type, &seqn);
261  switch (status) {
262  case X400_E_NOERROR:
263  fprintf(stderr, "MsgGet successfully got message\n");
264  break;
265  default :
266  fprintf(stderr, "Error from MsgGet: %s\n", X400msError(status));
267  /* tidily close the session */
268  status = X400msClose(sp);
269  exit(status);
270  break;
271  }
272 
273  if (type != X400_MSG_MESSAGE) {
274  /**********************************/
275  /* Report on the received Report */
276  /**********************************/
277  num_reports_rcvd++ ;
278  fprintf(stderr, "Got a report (printing only some attributes)\n");
279 
280  /* The ORADDRESS in the message is the (envelope) originator */
282  buffer, sizeof buffer, &length);
283  if (status != X400_E_NOERROR) {
284  fprintf(stderr, "Error from MsgGetStrParam: %s\n",
285  X400msError(status));
286  /* tidily close the session */
287  status = X400msClose(sp);
288  exit(status);
289  }
290  printf("Subject Identifier: %.*s\n", (int)length, buffer);
291 
292  /* Get the primary recipients */
293  for (n = 1;; n++) {
294  status = X400msRecipGet(mp, X400_RECIP_REPORT, n, &rp);
295  if (status == X400_E_NO_RECIP)
296  break;
297  if (status != X400_E_NOERROR) {
298  fprintf(stderr, "Error from RecipGet: %s\n",
299  X400msError(status));
300  /* tidily close the session */
301  status = X400msClose(sp);
302  exit(status);
303  }
304 
305  /* Note: recipient may not actually have an O/R address */
307  recipient_str,
308  sizeof recipient_str, &length);
309  if (status != X400_E_NOERROR) {
310  fprintf(stderr, "Error from RecipGetStrParam: %s\n",
311  X400msError(status));
312  /* tidily close the session */
313  status = X400msClose(sp);
314  exit(status);
315  }
316  /* print out the O/R Address of the report */
317  printf("Delivery Report for recipient %d: %.*s\n", n,
318  (int)length, recipient_str);
319 
320  /* The original message delivery time, if this attribute exists,
321  * then the report is a positive Delivery Report */
323  buffer, sizeof buffer, &length);
324 
325  if (status == X400_E_NOERROR) {
326  /* Positive Delivery Report */
327  printf("Delivery Time: %.*s\n", (int)length, buffer);
328  }
329  else {
330  /* Negative Delivery Report */
331  printf("Negative Delivery Report for recipient %d: %.*s\n", n,
332  (int)length, recipient_str);
333 
334  /* Supplementary Info to the report */
336  buffer, sizeof buffer,
337  &length);
338  if (status != X400_E_NOERROR) {
339  fprintf(stderr, "Error from RecipGetStrParam: %s\n",
340  X400msError(status));
341  buffer[0] = '\0';
342  }
343  printf("Supplementary Info: %.*s\n", (int)length, buffer);
344 
345  /* The reason why the message was not delivered */
346  status =
348  &intparam);
349  if (status != X400_E_NOERROR) {
350  fprintf(stderr, "Error from RecipGetIntParam: %s\n",
351  X400msError(status));
352  }
353  printf("Non-Delivery Reason: %d\n", intparam);
354 
355  /* The diagnostics of the report for this recipient */
356  status =
358  &intparam);
359  if (status != X400_E_NOERROR) {
360  fprintf(stderr, "Error from RecipGetIntParam: %s\n",
361  X400msError(status));
362  }
363  printf("Non-Delivery Diagnostic: %d\n", intparam);
364  }
365  }
366 
367  status = X400msMsgDelete(mp, 0);
368  if (status != X400_E_NOERROR) {
369  fprintf(stderr, "Error from X400msMsgDelete: %s\n",
370  X400msError(status));
371  }
372  return (status);
373  }
374 
375  /**********************************/
376  /* Report on the received Message */
377  /**********************************/
378 
379  num_messages_rcvd++ ;
380 
381  /* Size */
382  status =
384  &intparam);
385  if (status != X400_E_NOERROR) {
386  fprintf(stderr, "Error from MsgGetIntParam: %s\n",
387  X400msError(status));
388  }
389  printf("Size of Message: %d\n", intparam);
390 
391  /* The message identifier */
393  buffer, sizeof buffer, &length);
394  if (status != X400_E_NOERROR) {
395  fprintf(stderr, "Error from MsgGetStrParam: %s\n",
396  X400msError(status));
397  /* tidily close the session */
398  status = X400msClose(sp);
399  exit(status);
400  }
401  printf("Message Identifier: %.*s\n", (int)length, buffer);
402 
403  /* The ORADDRESS in the message is the (envelope) originator */
405  buffer, sizeof buffer, &length);
406  if (status != X400_E_NOERROR) {
407  fprintf(stderr, "Error from MsgGetStrParam: %s\n",
408  X400msError(status));
409  /* tidily close the session */
410  status = X400msClose(sp);
411  exit(status);
412  }
413  printf("Originator: %.*s\n", (int)length, buffer);
414 
415  /* Get the envelope recipients */
416  for (n = 1;; n++) {
417  status = X400msRecipGet(mp, X400_RECIP_ENVELOPE, n, &rp);
418  if (status == X400_E_NO_RECIP)
419  break;
420  if (status != X400_E_NOERROR) {
421  fprintf(stderr, "Error from RecipGet: %s\n", X400msError(status));
422  /* tidily close the session */
423  status = X400msClose(sp);
424  exit(status);
425  }
426 
427  /* Note: recipient may not actually have an O/R address */
429  buffer, sizeof buffer, &length);
430  if (status == X400_E_NOERROR) {
431  printf("Env Recipient %d: %.*s\n", n, (int)length, buffer);
432  }
433 
434  /* get back status of the Proof Of Del Request in the recipient */
436  &intparam);
437  if (status == X400_E_NOERROR) {
438  printf("Recipient proof of delivery request is %d\n", intparam);
439  } else {
440  fprintf(stderr, "Error getting proof of delivery request: %s\n",
441  X400msError(status));
442  }
443 
444  /* report content integrity check info if available */
445  get_cic(rp);
446 
447  /* return MessageToken info if available */
448  report_msg_token_info(rp);
449 
450  /* get and display the seccurity label if available */
451  get_sec_label(mp);
452  }
453 
454  /* Get the primary recipients */
455  for (n = 1;; n++) {
456  status = X400msRecipGet(mp, X400_RECIP_PRIMARY, n, &rp);
457  if (status == X400_E_NO_RECIP)
458  break;
459  if (status != X400_E_NOERROR) {
460  fprintf(stderr, "Error from RecipGet: %s\n", X400msError(status));
461  /* tidily close the session */
462  status = X400msClose(sp);
463  exit(status);
464  }
465 
466  /* Note: recipient may not actually have an O/R address */
468  buffer, sizeof buffer, &length);
469  if (status == X400_E_NOERROR) {
470  printf("Primary Recipient %d: %.*s\n", n, (int)length, buffer);
471  }
472 
473  status = X400msRecipGetIntParam(rp, X400_N_PRECEDENCE, &intparam);
474  if (status == X400_E_NOERROR) {
475  printf("Primary Recipient Precedence %d\n", intparam);
476  } else {
477  fprintf(stderr, "Error from RecipGet: %s\n", X400msError(status));
478  }
479 
480  }
481 
482  /* Subject is optional */
484  buffer, sizeof buffer, &length);
485  if (status == X400_E_NOERROR)
486  printf("Subject: %.*s\n", (int)length, buffer);
487 
488  /* And message text (or it could be another type) */
490  buffer, sizeof buffer, &length);
491  if (status == X400_E_NOERROR)
492  printf("Text:\n%.*s\n", (int)length, buffer);
493  else
494  printf("No IA5 Text content (%d: %s)\n", status, X400msError(status));
495 
496  /* get all the attachments */
497  printf("Getting body parts\n");
498  get_body_parts(mp);
499 
500  /* Deletes message in message store as well as internal copy */
501  status = X400msMsgDelete(mp, 0);
502 
503  return status;
504 }
505 
506 /*
507  * Recommended function to setup security env for verification.
508  * No digitial ID required - just a directory which contains
509  * trust anchors which are read as DER file (certificate.crt).
510  *
511  * The certificate (containing public key) is obtained from the message
512  * which is referenced in the message.
513  */
514 
515 static void setup_default_new_sec_env(
516  struct X400msSession *sp,
517  char *local_trusted_ca_certs_dir
518 )
519 {
520  int status;
521 
522  /* Directory containing trusted CA Certificates */
523  printf(" Adding %s as trusted CA cert dir\n", trusted_ca_certs_dir);
525  local_trusted_ca_certs_dir, -1);
526  if ( status != X400_E_NOERROR ) {
527  fprintf (stderr, "X400msSetStrDefault returned error: %s\n",
528  X400msError (status));
529  exit (status);
530  }
531 
532  return;
533 }
534 
535 /*
536  * Obsolete function to use to set up the security environment. This provides a
537  * directory in which PKCS12 files are checked to find one whose subject DN
538  * matches that of this client.
539  *
540  * Any self signed certificates found in the directory are treated as
541  * trusted.
542  */
543 
544 static void setup_default_old_sec_env(
545  struct X400msSession *sp,
546  char *id,
547  char *dn,
548  char *pw /* passphrase for private key in pkcs12 file */
549 )
550 {
551  int status;
552 
553  /* first set a default security identity. This passes in the name of a
554  * directory, which contains an x509 subdirectory in which all Identities
555  * are held */
556  /* X400msSetStrDefault(sp, X400_S_SEC_IDENTITY, "/var/isode/dsa-db/", -1);
557  * */
559 
560  /* select by DN which Identity is to be used (if there are several)
561  * Currently these must be PKCS12 files */
562  status = X400msSetStrDefault (sp, X400_S_SEC_IDENTITY_DN, dn, -1);
563  if ( status != X400_E_NOERROR ) {
564  fprintf (stderr, "X400msSetStrDefault returned error: %s\n",
565  X400msError (status));
566  exit (status);
567  }
568 
569  /* passphrase used to open the Identity */
571  if ( status != X400_E_NOERROR ) {
572  fprintf (stderr, "X400msSetStrDefault returned error: %s\n",
573  X400msError (status));
574  exit (status);
575  }
576  return;
577 }
578 
579 static void report_msg_token_info(
580  struct X400Recipient *rp
581 )
582 {
583  char buffer[BUFSIZ];
584  int status;
585  int param;
586  size_t length;
587 
588  status = X400msRecipGetIntParam(rp,
589  X400_N_MSGTOK_STATUS, &param);
590  if (status == X400_E_NO_VALUE) {
591  fprintf(stderr, "No MessageToken present in recipient\n");
592  /* no further information available */
593  return ;
594  } else if (status != X400_E_NOERROR) {
595  fprintf(stderr, "Error from RecipGetIntParam: %s (%d)\n",
596  X400msError(status),
598  fprintf(stderr, "Message Token status not available\n");
599  } else {
600  fprintf(stderr,
601  "Message Token status %d \n", param);
602  }
603 
604  switch (param) {
605  case X400_E_NOERROR:
606  fprintf(stderr, "Token OK (%d)\n", param);
607  break;
608  case X400_E_X509_ENV:
609  case X400_E_X509_INIT:
610  fprintf(stderr,
611  "Message Token validation cannot take place because the security environment is invalid (%d):\n",
612  param);
613  /* other values will not be available */
614  return ;
622  fprintf(stderr,
623  "Message Token validation failed (%d): %s\n",
624  param, X400msError(param));
625  break;
626  default:
627  fprintf(stderr,
628  "Unexpected Message Token validation result (%d): %s\n",
629  param, X400msError(param));
630  break;
631 
632  }
633 
634  show_certificate (rp, X400_N_CERT_MSGTOK, "message-token");
635 
636  status = X400msRecipGetStrParam(rp,
638  buffer, sizeof buffer, &length);
639  if (status != X400_E_NOERROR) {
640  fprintf(stderr, "Error from RecipGetStrParam: %s\n",
641  X400msError(status));
642 
643  fprintf(stderr, "recipient in token not available\n");
644  } else {
645  fprintf(stderr,
646  "Message Token(%u): recipient in Token '%.*s'\n",
647  (unsigned)length, (int)length, buffer);
648  }
649 
650  status = X400msRecipGetStrParam(rp,
652  buffer, sizeof buffer, &length);
653  if (status != X400_E_NOERROR) {
654  fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
655  X400msError(status),
657  fprintf(stderr, "Message Token DER not available\n");
658  } else {
659  fprintf(stderr,
660  "Message Token DER available (%u bytes)\n", (unsigned)length);
661  }
662 
663  status = X400msRecipGetIntParam(rp,
664  X400_N_MSGTOK_SEQ_NUM, &param);
665  if (status != X400_E_NOERROR) {
666  fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
667  X400msError(status),
669  fprintf(stderr, "Message Token seq num not available\n");
670  } else {
671  fprintf(stderr,
672  "Message Token seq num %d \n", param);
673  }
674 
675  status = X400msRecipGetStrParam(rp,
677  buffer, sizeof buffer, &length);
678  if (status != X400_E_NOERROR) {
679  fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
680  X400msError(status),
682  fprintf(stderr, "Message Token Security Label DER not available\n");
683  } else {
684  fprintf(stderr,
685  "Message Token Security Label DER available (%u bytes)\n", (unsigned)length);
686  fprintf(stderr, "Security Label from Message Token is:\n");
687  print_sec_label((unsigned char *)buffer, length);
688  }
689 
690  /* get back status of the Content Integrity Check in the message token */
692  &param);
693  if (status == X400_E_NO_VALUE) {
694  printf("No Content Integrity Check in token\n");
695  } else if (status != X400_E_NOERROR) {
696  printf("Error from RecipGetIntParam: %s\n", X400msError(status));
697 
698  } else {
699 
700  /* report CIC information */
701  switch (param) {
702  case X400_E_NOERROR:
703  printf("Content Integrity Check in token succeeded\n");
704  break;
705  default:
706  printf("Content Integrity Check in token error (%d): %s\n",
707  param, X400msError(param));
708  break;
709  }
710 
711  status = X400msRecipGetStrParam(rp,
713  buffer, sizeof buffer, &length);
714  if (status != X400_E_NOERROR) {
715  fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
716  X400msError(status),
718  fprintf(stderr, "Message Token Content Integrity Check DER not available\n");
719  } else {
720  fprintf(stderr,
721  "Message Token Content Integrity Check DER available (%u bytes)\n",
722  (unsigned)length);
723  }
724 
725  show_certificate (rp, X400_N_CERT_MSGTOK_CIC, "token CIC");
726  }
727 
728  status = X400msRecipGetIntParam(rp,
729  X400_N_MSGTOK_PODR_STATUS, &param);
730  if (status != X400_E_NOERROR) {
731  fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
732  X400msError(status),
734  fprintf(stderr, "Message Token proof of delivery status not available\n");
735  } else {
736  fprintf(stderr,
737  "Message Token proof of delivery status %d \n", param);
738  }
739 
740  status = X400msRecipGetIntParam(rp,
742  if (status != X400_E_NOERROR) {
743  fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
744  X400msError(status),
746  fprintf(stderr, "Message Token security label status not available\n");
747  } else {
748  fprintf(stderr,
749  "Message Token security label status %d \n", param);
750  }
751 
752  status = X400msRecipGetIntParam(rp,
754  if (status != X400_E_NOERROR) {
755  fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
756  X400msError(status),
758  fprintf(stderr, "Message Token recip status not available\n");
759  } else {
760  fprintf(stderr,
761  "Message Token recip status %d \n", param);
762  }
763 
764 
765  return;
766 }
767 
768 
769 static int get_sec_label(
770  struct X400msMessage *mp
771 )
772 {
773  unsigned char slab_buffer[XML_BUFSIZE];
774  int status;
775  size_t length;
776 
777  status = X400msMsgGetStrParam(mp,
779  (char*)slab_buffer,
780  XML_BUFSIZE,
781  &length);
782  if (status == X400_E_NO_VALUE) {
783  printf("No security label\n");
784  } else if (status != X400_E_NOERROR) {
785  fprintf(stderr,"Failed to fetch security label: %d",status);
786  return (status);
787  } else {
788  fprintf(stderr, "Security Label from envelope is:\n");
789  print_sec_label(slab_buffer, length);
790  }
791  return X400_E_NOERROR;
792 }
793 
794 static void print_sec_label(
795  unsigned char slab_buffer[],
796  unsigned int length
797 )
798 {
799 
800  char xml_buffer[XML_BUFSIZE];
801  int status;
802 
803  status = SecLabelInit("Example program");
804  if (status != SECLABEL_E_NOERROR) {
805  fprintf(stderr, "SecLabelInit returned error %d\n", status);
806  return ;
807  }
808 
809  status = SecLabelPrint(slab_buffer,
810  length,
811  xml_buffer,
812  XML_BUFSIZE);
813 
814  if (status != SECLABEL_E_NOERROR) {
815  fprintf(stderr, "SecLabelParse returned error %d\n", status);
816  return ;
817  }
818 
819  /* You could now write out the XML file, or parse it in memory..*/
820  printf("Got security label:%s\n", xml_buffer);
821  return;
822 }
823 
824 static int get_cic(
825  struct X400Recipient *rp
826 )
827 {
828  char buffer[BUFSIZ];
829  int status, cic_status;
830  int intparam;
831  size_t length;
832 
833  /* get back status of the Content Integrity Check in the recipient */
835  &intparam);
836  if (cic_status == X400_E_NO_VALUE) {
837  printf("No Content Integrity Check in recipient\n");
838  return X400_E_NOERROR;
839  } else if (cic_status != X400_E_NOERROR) {
840  printf("Error from RecipGetIntParam: %s\n", X400msError(cic_status));
841  return cic_status;
842  }
843 
844  /* report CIC information */
845  switch (intparam) {
846  case X400_E_NOERROR:
847  printf("Content Integrity Check succeeded\n");
848  break;
849  default:
850  printf("Content Integrity Check error (%d): %s\n",
851  intparam, X400msError(intparam));
852  break;
853  }
854 
855  /* Return the Content Integrity Check */
857  buffer, sizeof buffer, &length);
858  if (status != X400_E_NOERROR) {
859  fprintf(stderr, "Error getting recipient cic: %s\n",
860  X400msError(status));
861  } else {
862  printf("Content Integrity Check found in recipient (%d)\n",
863  (int)length);
864  }
865 
866  show_certificate (rp, X400_N_CERT_RECIP_CIC, "recipient CIC");
867 
868  return X400_E_NOERROR;
869 }
870 
871 static void show_certificate (
872  struct X400Recipient *rp,
873  int certtype,
874  const char *tag)
875 {
876  int status;
877  struct X400Certificate *cert;
878  char buffer[BUFSIZ];
879  size_t length;
880  int paramval;
881 
882  status = X400RecipGetCert (rp, certtype, &cert);
883  if ( status != X400_E_NOERROR ) {
884  fprintf (stderr, "Error getting %s certificate: %s\n",
885  tag, X400msError (status));
886  return;
887  }
888 
889  /* Return the subject DN from Orig cert */
891  buffer, sizeof buffer, &length);
892  if (status != X400_E_NOERROR) {
893  fprintf(stderr, "Error getting subject of cert used for %s: %s\n",
894  tag, X400msError(status));
895  } else {
896  printf("Subject of Cert used to verify %s (%.*s)\n",
897  tag, (int)length, buffer);
898  }
899 
900  /* Return the issuer DN from Orig cert */
902  buffer, sizeof buffer, &length);
903  if (status != X400_E_NOERROR) {
904  fprintf(stderr, "Error getting issuer of cert used for %s: %s\n",
905  tag, X400msError(status));
906  } else {
907  printf("Issuer of Cert used to verify %s (%.*s)\n",
908  tag, (int)length, buffer);
909  }
910 
911  /* Return the serial number from Orig cert used to verify the
912  * Content Integrity Check */
914  buffer, sizeof buffer, &length);
915  if (status != X400_E_NOERROR) {
916  fprintf(stderr, "Error getting serial num of cert used for %s: %s\n",
917  tag, X400msError(status));
918  } else {
919  printf("Serial Num of Cert used to verify %s (%.*s)\n",
920  tag, (int)length, buffer);
921  }
922 
923  /* Return the Orig cert used to verify the Content Integrity Check */
924  status = X400CertGetStrParam(cert, X400_S_CERT_BER,
925  buffer, sizeof buffer, &length);
926  if (status != X400_E_NOERROR) {
927  fprintf(stderr, "Error getting cert der used for %s: %s\n",
928  tag, X400msError(status));
929  } else {
930  printf(
931  "Returned Cert used to verify %s (%d)\n",
932  tag, (int)length);
933  }
934 
935  /* Find any ORaddress subject alt name and its status */
936  status = X400CertGetStrParam(cert, X400_S_OR_ADDRESS,
937  buffer, sizeof buffer, &length);
938  if (status != X400_E_NOERROR) {
939  if ( status == X400_E_NO_VALUE ) {
940  fprintf(stderr, "No ORaddress subject alt. name\n");
941  } else {
942  fprintf(stderr, "Error from CertGetStrParam: %s\n",
943  X400msError(status));
944  return;
945  }
946  } else {
947  fprintf(stderr, "ORaddress subject alt name: '%.*s'\n",
948  (int)length, buffer);
949  }
950 
951  status = X400CertGetIntParam(cert, X400_N_CERT_ORADDRESS_STATUS, &paramval);
952 
953  if (status != X400_E_NOERROR) {
954  fprintf(stderr, "Error from CertGetStrParam: %s\n",
955  X400msError(status));
956  return;
957  }
958 
959  fprintf(stderr, "ORaddress subject alt name status: %s\n",
960  X400msError (paramval));
961 }
962 
963 static void usage(void) {
964  printf("usage: %s\n", optstr);
965  printf("\t where:\n");
966  printf("\t -u : Don't prompt to override defaults \n");
967  printf("\t -3 : Use P3 connection \n");
968  printf("\t -7 : Use P7 connection \n");
969  printf("\t -m : OR Address in P7 bind arg \n");
970  printf("\t -d : DN in P7 bind arg \n");
971  printf("\t -p : Presentation Address of P7 Store \n");
972  printf("\t -w : P7 password of P7 user \n");
973  printf("\t -M : OR Address in P3 bind arg \n");
974  printf("\t -D : DN in P3 bind arg \n");
975  printf("\t -P : Presentation Address of P3 server\n");
976  printf("\t -W : P3 password of P3 user \n");
977  printf("\t -e : Security Environment (dir with x509 subdir): obsolete, use -Y <p12file>\n");
978  printf("\t -x : DN of X.509 Digital Identity\n");
979  printf("\t -b : Passphrase for private key in PKCS12 file\n");
980  printf("\t -E : Fetch messages until all read\n");
981  printf("\t -Y : Filename of PKCS12 file containing Digital Identity\n");
982  printf("\t -U : Directory containing trust anchors\n");
983  return;
984 }
#define X400_MSG_MESSAGE
Definition: x400_att.h:29
#define X400_S_CERT_SERIAL_NUM
Definition: x400_att.h:1494
#define X400_S_MSGTOK_RECIP
Definition: x400_att.h:1408
#define X400_S_LOG_CONFIGURATION_FILE
Definition: x400_att.h:1080
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:1417
#define X400_S_CERT_SUBJECT_DN
Definition: x400_att.h:1488
#define X400_S_SUBJECT_IDENTIFIER
Definition: x400_att.h:1027
#define X400_N_CONTENT_LENGTH
Definition: x400_att.h:408
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:172
#define X400_S_SEC_IDENTITY
Definition: x400_att.h:551
#define X400_E_X509_CERT_INVALID
Definition: x400_att.h:196
#define X400_N_MSGTOK_RECIP_STATUS
Definition: x400_att.h:1420
int X400msMsgGet(struct X400msSession *sp, int number, struct X400msMessage **mpp, int *typep, int *seqp)
Get message object for transfer out from MTA.
#define X400_S_MSGTOK_CIC
Definition: x400_att.h:1426
#define X400_N_MSGTOK_STATUS
Definition: x400_att.h:1399
#define X400_N_PRECEDENCE
Definition: x400_att.h:682
#define X400_S_SUPPLEMENTARY_INFO
Definition: x400_att.h:1030
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:181
#define X400_E_NO_RECIP
Definition: x400_att.h:109
int X400msClose(struct X400msSession *sp)
Close a X400 Session.
#define X400_S_MSGTOK_SEC_LAB
Definition: x400_att.h:1411
#define X400_E_NO_VALUE
Definition: x400_att.h:100
#define X400_N_PROOF_OF_DEL_REQ
Definition: x400_att.h:974
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:795
#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:1497
#define X400_S_OR_ADDRESS
Definition: x400_att.h:346
#define X400_S_MSGTOK_DER
Definition: x400_att.h:1402
#define X400_S_SEC_IDENTITY_PASSPHRASE
Definition: x400_att.h:557
#define X400_S_MESSAGE_IDENTIFIER
Definition: x400_att.h:402
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:193
#define X400_N_CERT_RECIP_CIC
Definition: x400_att.h:1472
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:1310
#define X400_RECIP_PRIMARY
Definition: x400_att.h:293
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:560
#define X400_S_CERT_BER
Definition: x400_att.h:1485
#define X400_E_X509_VERIFY_FAIL_UNSUPPORTED_ALG
Definition: x400_att.h:190
#define X400_N_RECIP_CIC_STATUS
Definition: x400_att.h:1437
#define X400_E_X509_VERIFY_FAIL_INCOMPAT_ALG
Definition: x400_att.h:187
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:1039
#define X400_B_RETURN_VERIFICATION_ERRORS
Definition: x400_att.h:1087
X400 MA/MS (P3/P7) Interface.
#define X400_S_CERT_ISSUER_DN
Definition: x400_att.h:1491
#define X400_N_CERT_MSGTOK
Definition: x400_att.h:1469
#define X400_N_MSGTOK_SEQ_NUM
Definition: x400_att.h:1405
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:199
#define X400_E_X509_INIT
Definition: x400_att.h:178
#define X400_S_SUBJECT
Definition: x400_att.h:719
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:332
#define X400_S_SEC_TRUSTED_CERTS_DIR
Definition: x400_att.h:578
#define X400_S_RECIP_CIC
Definition: x400_att.h:1440
#define X400_N_NON_DELIVERY_DIAGNOSTIC
Definition: x400_att.h:1042
#define X400_N_MSGTOK_PODR_STATUS
Definition: x400_att.h:1414
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_MSGTOK_CIC_STATUS
Definition: x400_att.h:1423
#define X400_RECIP_REPORT
Definition: x400_att.h:311
int X400msMsgDelete(struct X400msMessage *mp, int retain)
Delete message object.
#define X400_N_CERT_MSGTOK_CIC
Definition: x400_att.h:1475
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_E_X509_VERIFY_FAIL_NO_PUBKEY
Definition: x400_att.h:184
#define X400_S_MESSAGE_DELIVERY_TIME
Definition: x400_att.h:439