x400_mssend_sign_multi_addr.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  * @VERSION@
13  * Simple example program for transferring a message into the gateway.
14  * The security environment is set up so that messages are signed.
15  */
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 
21 #include <x400_msapi.h>
22 #include "example.h"
23 
24 static char *optstr = "u37m:d:p:w:M:D:P:W:r:o:O:r:g:G:c:l:R:y:C:iaqsAve:x:b:f:";
25 
26 /* These are the data items used to construct the message for submission */
27 static char *default_recip = "/CN=lppt1/OU=lppt/O=attlee/PRMD=TestPRMD/ADMD=TestADMD/C=GB/";
28 char *recip;
29 /* static char *content_id = "030924.140212"; */
30 static char *content_id = "030924.140212";
31 static const char text[] = "First line\r\nSecond line\r\n";
32 static char *binary_data;
33 
34 static int setup_msg_sec_env = 1;
35 
36 /* local functions */
37 
38 static void usage(void) ;
39 static int send_msg(
40  int contype,
41  char *orn,
42  char *def_dn,
43  char *pa,
44  char *password);
45 
46 static int submit_msg(
47  char *orn,
48  struct X400msSession *sp /* session object */
49 );
50 
51 static int setup_default_new_sec_env(
52  struct X400msSession *sp,
53  char *identity_filename,
54  char *pw
55 );
56 
57 static int setup_default_old_sec_env(
58  struct X400msSession *sp,
59  char *id,
60  char *dn,
61  char *pw
62 );
63 
64 static int setup_msg_new_sec_env(
65  struct X400msMessage *mp, /* message object */
66  char *identity_filename,
67  char *pw
68 );
69 
70 static int setup_msg_old_sec_env(
71  struct X400msMessage *mp, /* message object */
72  char *id,
73  char *dn,
74  char *pw
75 );
76 
77 /* start here */
78 int main (
79  int argc,
80  char **argv
81 )
82 {
83  char pa[BUFSIZ];
84  char orn[BUFSIZ];
85  char *def_oraddr;
86  char *def_dn;
87  char *def_pa;
88  int contype;
89  int status = 0;
90  char password[BUFSIZ];
91  int num_msgs = 2;
92 
93  if (get_args(argc, argv, optstr)) {
94  usage();
95  exit(-1);
96  }
97 
98  printf("Connection type (0 = P7, 1 = P3) [%d]: ", x400_contype);
99  contype = ic_fgetc(x400_contype, stdin);
100  if (contype != 10)
101  ic_fgetc(x400_contype, stdin);
102 
103  if ((contype != '0') && (contype != '1'))
104  contype = x400_contype;
105  else
106  contype -= '0';
107 
108  if (contype == 0) {
109  def_oraddr = x400_ms_user_addr;
110  def_dn = x400_ms_user_dn;
111  def_pa = x400_ms_presentation_address;
112  } else {
113  def_oraddr = x400_mta_user_addr;
114  def_dn = x400_mta_user_dn;
115  def_pa = x400_mta_presentation_address;
116  }
117 
118  printf("Your ORAddress [%s] > ", def_oraddr);
119  ic_fgets (orn, sizeof orn, stdin);
120 
121  if ( orn[strlen(orn)-1] == '\n' )
122  orn[strlen(orn)-1] = '\0';
123 
124  if (orn[0] == '\0')
125  strcpy(orn, def_oraddr);
126 
127  /* Prompt for password; note: reflected. */
128  printf ("Password [%s]: ",
129  contype == 0 ? x400_p7_password : x400_p3_password);
130  if ( ic_fgets (password, sizeof password, stdin) == NULL )
131  exit (1);
132 
133  if (password[strlen(password)-1] == '\n' )
134  password[strlen(password)-1] = '\0';
135  if (password[0] == '\0')
136  strcpy(password, contype == 0 ? x400_p7_password : x400_p3_password);
137 
138  /* Presentation Address */
139  printf("Presentation Address [%s] > ", def_pa);
140  ic_fgets (pa, sizeof pa, stdin);
141 
142  if ( pa[strlen(pa)-1] == '\n' )
143  pa[strlen(pa)-1] = '\0';
144 
145  if (pa[0] == '\0')
146  strcpy(pa, def_pa);
147 
148  while (num_msgs--) {
149  if ((status = send_msg(contype, orn, def_dn, pa, password))
150  != X400_E_NOERROR ) {
151  fprintf (stderr, "Error in sending message\n");
152  exit (status);
153  }
154  }
155  return (status);
156 }
157 
158 static int send_msg(
159  int contype,
160  char *orn,
161  char *def_dn,
162  char *pa,
163  char *password
164 )
165 {
166  struct X400msSession *sp; /* session object */
167 
168  int status;
169 
170 
171  /* we've got what we need - now open an API session */
172  status = X400msOpen (contype, orn, def_dn, password, pa, NULL, &sp);
173  if ( status != X400_E_NOERROR ) {
174  fprintf (stderr, "Error in Open: %s\n", X400msError (status));
175  fprintf (stderr, "%s %s %s\n", orn, def_dn, pa);
176  return (status);
177  }
178 
179  /* setup logging */
180  X400msSetStrDefault(sp, X400_S_LOG_CONFIGURATION_FILE, "x400api.xml", 0);
181 
182  /* Set up the security environment.
183  *
184  * The security env can be specified the new way (recommended) using
185  * a PKCS12 filename and passphrase, or as a directory (deprecated and
186  * obsolete).
187  *
188  * If the ID is specified as a directory, in which the subdirectory
189  * "x509" is expected to contain one or more PKCS12 files.
190  * The appropriate Digital Identity is determined from the
191  * DN of the subject, and the passphrase is used to decrypt
192  * the private key.
193  */
194  if (use_new_sec_env) {
195  status = setup_default_new_sec_env(sp, identity_filename, passphrase);
196  } else {
197  status = setup_default_old_sec_env(sp, security_id, identity_dn,
198  passphrase);
199  }
200  if ( status != X400_E_NOERROR ) {
201  fprintf (stderr, "Can't setup security environment\n");
202  return (status);
203  }
204 
205  printf("sending message 1\n");
206  status = submit_msg(orn, sp);
207  if ( status != X400_E_NOERROR ) {
208  fprintf (stderr, "Can't submit\n");
209  return (status);
210  }
211 
212  /* might want to test changing the default security env here */
213 
214  printf("sending message 2\n");
215  status = submit_msg(orn, sp);
216  if ( status != X400_E_NOERROR ) {
217  fprintf (stderr, "Can't submit\n");
218  return (status);
219  }
220 
221  printf("sending message 3\n");
222  status = submit_msg(orn, sp);
223  if ( status != X400_E_NOERROR ) {
224  fprintf (stderr, "Can't submit\n");
225  return (status);
226  }
227 
228  status = X400msClose (sp);
229  if ( status != X400_E_NOERROR ) {
230  fprintf (stderr, "X400msClose returned error: %s\n", X400msError (status));
231  return (status);
232  }
233 
234  return status;
235 }
236 
237 static int submit_msg(
238  char *orn,
239  struct X400msSession *sp /* session object */
240 )
241 {
242  struct X400msMessage *mp; /* message object */
243  struct X400Recipient *rp; /* recipient object */
244  char tmp[BUFSIZ];
245  FILE *fp = NULL;
246  int fs=0;
247  int status;
248 
249  if (x400_default_recipient != NULL)
250  recip = x400_default_recipient;
251  else
252  recip = default_recip;
253 
254  printf("Message recipient [%s]: ", recip);
255  ic_fgets (tmp, sizeof tmp, stdin);
256 
257  if ( tmp[strlen(tmp)-1] == '\n' )
258  tmp[strlen(tmp)-1] = '\0';
259  if (strlen(tmp) != 0)
260  recip = strdup(tmp);
261 
262  printf("Subject [%s]: ", subject);
263  ic_fgets (tmp, sizeof tmp, stdin);
264 
265  if ( tmp[strlen(tmp)-1] == '\n' )
266  tmp[strlen(tmp)-1] = '\0';
267  if (strlen(tmp) != 0)
268  subject = strdup(tmp);
269 
270  status = X400msMsgNew (sp, X400_MSG_MESSAGE, &mp);
271  if ( status != X400_E_NOERROR ) {
272  fprintf (stderr, "x400msMsgNew returned error: %s\n", X400msError (status));
273  return (status);
274  }
275 
276  /* Set up the security environment for this message overriding the
277  * default security env.
278  *
279  * The security env can be specified the new way (reccommened) using
280  * a PKCS12 filename and passphrase, or as a directory (deprecated and
281  * obsolete).
282  *
283  * If the ID is specified as a pathname, in which the subdirectory
284  * "x509" is expected to contain one or more PKCS12 files.
285  * The appropriate Digital Identity is determined from the
286  * DN of the subject, and the passphrase is used to decrypt
287  * the private key.
288  */
289  if (setup_msg_sec_env) {
290  if (use_new_sec_env) {
291  status = setup_msg_new_sec_env(mp, identity_filename, passphrase);
292  if ( status != X400_E_NOERROR ) {
293  fprintf (stderr, "Can't setup new security environment\n");
294  return (status);
295  }
296  } else {
297  status = setup_msg_old_sec_env(mp, security_id, identity_dn2,
298  passphrase);
299  if ( status != X400_E_NOERROR ) {
300  fprintf (stderr, "Can't setup old security environment\n");
301  return (status);
302  }
303  }
304  }
305 
306  /* Instruct the X400msMsgSend() function to generate a MOAC (signature) for
307  * the message Instruct the X400msMsgSend() function to generate a MOAC
308  * (signature) for the message
309  * The default attributes will be used unless the attributes are
310  * also included in the message eg by calling setup_msg_sec_env() above
311  */
312  status = X400msMsgAddIntParam (mp, X400_B_SEC_GEN_MOAC, 1);
313  if ( status != X400_E_NOERROR ) {
314  fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n", X400msError (status));
315  return (status);
316  }
317 
318  status = X400msRecipNew (mp, X400_RECIP_STANDARD, &rp);
319  if ( status != X400_E_NOERROR ) {
320  fprintf (stderr, "x400msRecipNew returned error: %s\n", X400msError (status));
321  return (status);
322  }
323 
324  status = X400msRecipAddStrParam (rp, X400_S_OR_ADDRESS, recip, -1);
325  if ( status != X400_E_NOERROR ) {
326  fprintf (stderr, "x400msRecipAddStrParam returned error: %s\n", X400msError (status));
327  return (status);
328  }
329 
330  status = X400msRecipAddStrParam (rp, X400_S_DIRECTORY_NAME, "CN=recipient;c=gb", -1);
331  if ( status != X400_E_NOERROR ) {
332  fprintf (stderr, "x400msRecipAddStrParam returned error: %s\n", X400msError (status));
333  return (status);
334  }
335 
336  status = X400msMsgAddStrParam (mp, X400_S_OR_ADDRESS, orn, -1);
337  if ( status != X400_E_NOERROR ) {
338  fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n", X400msError (status));
339  return (status);
340  }
341 
342  status = X400msMsgAddStrParam (mp, X400_S_DIRECTORY_NAME, "CN=originator;c=gb", -1);
343  if ( status != X400_E_NOERROR ) {
344  fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n", X400msError (status));
345  return (status);
346  }
347 
348  /* Ask for +ve and -ve delivery reports */
350  if ( status != X400_E_NOERROR ) {
351  fprintf (stderr, "x400msRecipAddStrParam returned error: %s\n", X400msError (status));
352  return (status);
353  }
354 
355  /* Ask for +ve and -ve read receipts */
357  if ( status != X400_E_NOERROR ) {
358  fprintf (stderr, "x400msRecipAddStrParam returned error: %s\n", X400msError (status));
359  return (status);
360  }
361 
363  content_id, -1);
364  if ( status != X400_E_NOERROR ) {
365  fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n", X400msError (status));
366  return (status);
367  }
368 
369  status = X400msMsgAddStrParam (mp, X400_S_SUBJECT, subject, -1);
370  if ( status != X400_E_NOERROR ) {
371  fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n", X400msError (status));
372  return (status);
373  }
374 
375  status = X400msMsgAddStrParam (mp, X400_T_ISO8859_1, text, -1);
376  if ( status != X400_E_NOERROR ) {
377  fprintf (stderr, "x400ms returned error: %s\n", X400msError (status));
378  return (status);
379  }
380 
381  /* now an IA5 body part using the bodypart func */
382  status = X400msMsgAddAttachment (mp, X400_T_IA5TEXT, text, strlen(text));
383  if ( status != X400_E_NOERROR ) {
384  printf("failed to add X400_T_IA5TEXT BP\n");
385  return (status);
386  }
387 
388  /* or a Binary body part using the bodypart func */
389  if (filename_to_send != NULL) {
390  binary_data = (char *) malloc(100000);
391  if ( binary_data == NULL )
392  return X400_E_NOMEMORY;
393  fp = fopen(filename_to_send, "r");
394  if (fp == (FILE *)NULL) {
395  printf("Cannot open binary file\n");
396  return (X400_E_SYSERROR);
397  }
398  if ((fs = fread (binary_data, sizeof(char), 100000/sizeof(char), fp) ) == -1) {
399  printf("Cannot read from binary file\n");
400  return (X400_E_SYSERROR);
401  }
402  fclose(fp);
403 
404  status = X400msMsgAddAttachment (mp, X400_T_BINARY, binary_data, fs);
405  if ( status != X400_E_NOERROR ) {
406  printf("failed to add X400_T_BINARY BP\n");
407  return (status);
408  }
409  } else {
410  printf("no binary file set - not sending X400_T_BINARY\n");
411  }
412 
413  status = X400msMsgSend (mp);
414  if ( status != X400_E_NOERROR ) {
415  fprintf (stderr, "x400msMsgSend returned error: %s\n", X400msError (status));
416  return (status);
417  } else {
418  printf("Message submitted successfully\n");
419  }
420 
421  status = X400msMsgDelete (mp, 0);
422  if ( status != X400_E_NOERROR ) {
423  fprintf (stderr, "x400msMsgDelete returned error: %s\n", X400msError (status));
424  return (status);
425  }
426 
427  mp = NULL;
428  rp = NULL;
429 
430  return (status);
431 }
432 
433 static int setup_default_new_sec_env(
434  struct X400msSession *sp,
435  char *identity,
436  char *pw
437 )
438 {
439  int status;
440 
441  /* Filename of the Digital Identity (PKCS12 file) */
443  identity, -1);
444  if ( status != X400_E_NOERROR ) {
445  fprintf (stderr, "X400msSetStrDefault returned error: %s\n",
446  X400msError (status));
447  return (status);
448  }
449 
450  /* passphrase used to open the Identity */
452  if ( status != X400_E_NOERROR ) {
453  fprintf (stderr, "X400msSetStrDefault returned error: %s\n",
454  X400msError (status));
455  return (status);
456  }
457 
458  /* test the sec env */
459  status = X400msTestSecurityEnv (sp);
460  if ( status != X400_E_NOERROR ) {
461  fprintf (stderr, "X400msTestSecurityEnv returned error: %s\n",
462  X400msError (status));
463  return (status);
464  }
465 
466  return status;
467 }
468 
469 static int setup_default_old_sec_env(
470  struct X400msSession *sp,
471  char *id,
472  char *dn,
473  char *pw
474 )
475 {
476  int status;
477 
478  /* first set a default security identity. This passes in the name of a
479  * directory, which contains an x509 subdirectory in which all Identities
480  * are held */
482 
483  /* select by DN which Identity is to be used (if there are several)
484  * Currently these must be PKCS12 files */
485  status = X400msSetStrDefault (sp, X400_S_SEC_IDENTITY_DN, dn, -1);
486  if ( status != X400_E_NOERROR ) {
487  fprintf (stderr, "X400msSetStrDefault returned error: %s\n",
488  X400msError (status));
489  return (status);
490  }
491 
492  /* passphrase used to open the Identity */
494  if ( status != X400_E_NOERROR ) {
495  fprintf (stderr, "X400msSetStrDefault returned error: %s\n",
496  X400msError (status));
497  return (status);
498  }
499 
500  return status;
501 }
502 
503 static int setup_msg_new_sec_env(
504  struct X400msMessage *mp, /* message object */
505  char *identity,
506  char *pw
507 )
508 {
509  int status;
510 
511  /* Filename of the Digital Identity (PKCS12 file) */
513  identity, -1);
514  if ( status != X400_E_NOERROR ) {
515  fprintf (stderr, "X400msMsgAddStrParam returned error: %s\n",
516  X400msError (status));
517  return (status);
518  }
519 
520  /* security additions */
522  if ( status != X400_E_NOERROR ) {
523  fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n",
524  X400msError (status));
525  return (status);
526  }
527  return (status);
528 }
529 
530 static int setup_msg_old_sec_env(
531  struct X400msMessage *mp, /* message object */
532  char *id,
533  char *dn,
534  char *pw
535 )
536 {
537  int status;
538 
539  /* overide the default security environment by specifying a new set of
540  * attibutes, and put them into the message */
541  /* security additions */
542  status = X400msMsgAddStrParam (mp, X400_S_SEC_IDENTITY, id, -1);
543  /* status = X400msMsgAddStrParam (mp, X400_S_SEC_IDENTITY, "/var/isode/dsa-db", -1); */
544  if ( status != X400_E_NOERROR ) {
545  fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n",
546  X400msError (status));
547  return (status);
548  }
549 
550  /* security additions */
551  status = X400msMsgAddStrParam (mp, X400_S_SEC_IDENTITY_DN, dn, -1);
552  if ( status != X400_E_NOERROR ) {
553  fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n",
554  X400msError (status));
555  return (status);
556  }
557 
558  /* security additions */
560  if ( status != X400_E_NOERROR ) {
561  fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n",
562  X400msError (status));
563  return (status);
564  }
565  return (status);
566 }
567 
568 static void usage(void) {
569  printf("usage: %s\n", optstr);
570  printf("\t where:\n");
571  printf("\t -u : Don't prompt to override defaults \n");
572  printf("\t -3 : Use P3 connection \n");
573  printf("\t -7 : Use P7 connection \n");
574  printf("\t -m : OR Address in P7 bind arg \n");
575  printf("\t -d : DN in P7 bind arg \n");
576  printf("\t -p : Presentation Address of P7 Store \n");
577  printf("\t -w : P7 password of P7 user \n");
578  printf("\t -M : OR Address in P3 bind arg \n");
579  printf("\t -D : DN in P3 bind arg \n");
580  printf("\t -P : Presentation Address of P3 server\n");
581  printf("\t -W : P3 password of P3 user \n");
582  printf("\t -o : Originator \n");
583  printf("\t -O : Originator Return Address \n");
584  printf("\t -r : Recipient\n");
585  printf("\t -l : Logline\n");
586  printf("\t -y : Priority (0 - normal, 1 - non-urgent, 2 - urgent \n");
587  printf("\t -C : Content Type (2/22/772/OID) \n");
588  printf("\t -i : Implicit conversion prohibited = TRUE \n");
589  printf("\t -a : Alternate Recipient Prohibited = TRUE \n");
590  printf("\t -q : Content Return Request = TRUE \n");
591  printf("\t -s : Disclosure of Recipient = FALSE \n");
592  printf("\t -A : Recipient Reassignment Prohibited = FALSE \n");
593  printf("\t -v : Conversion with Loss Prohibited = FALSE \n");
594  printf("\t -e : Security Environment (dir with x509 subdir): obsolete, use -Y <p12file>\n");
595  printf("\t -x : DN of X.509 Digital Identity\n");
596  printf("\t -b : Passphrase for private key in PKCS12 file\n");
597  printf("\t -f : Filename to transfer as binary bp\n");
598  printf("\t -Y : Filename of PKCS12 file containing Digital Identity\n");
599  return;
600 }
601 
602 
#define X400_S_LOG_CONFIGURATION_FILE
Definition: x400_att.h:1092
int X400msMsgSend(struct X400msMessage *mp)
Send message object.
int X400msMsgAddAttachment(struct X400msMessage *mp, int type, const char *string, size_t length)
Add attachment to the message.
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_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.
int X400msClose(struct X400msSession *sp)
Close a X400 Session.
int X400msMsgAddIntParam(struct X400msMessage *mp, int paramtype, int value)
Add integer-valued parameter to the message.
#define X400_T_BINARY
Definition: x400_att.h:825
int X400msRecipAddIntParam(struct X400Recipient *rp, int paramtype, int value)
Add integer-valued parameter to the message.
int X400msRecipAddStrParam(struct X400Recipient *rp, int paramtype, const char *value, size_t length)
Add string-valued parameter to the message.
#define X400_S_DIRECTORY_NAME
Definition: x400_att.h:397
int X400msRecipNew(struct X400msMessage *mp, int type, struct X400Recipient **rpp)
Add new recipient to a message.
#define X400_T_ISO8859_1
Definition: x400_att.h:809
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_S_SEC_IDENTITY_DN
Definition: x400_att.h:563
#define X400_RECIP_STANDARD
Definition: x400_att.h:341
int X400msMsgNew(struct X400msSession *sp, int type, struct X400msMessage **mpp)
Creates new message.
#define X400_S_CONTENT_IDENTIFIER
Definition: x400_att.h:414
#define X400_S_SEC_IDENTITY_PASSPHRASE
Definition: x400_att.h:560
#define X400_E_NOERROR
Definition: x400_att.h:46
#define X400_N_REPORT_REQUEST
Definition: x400_att.h:654
X400 MA/MS (P3/P7) Interface.
#define X400_S_SEC_IDENTITY_FILE
Definition: x400_att.h:578
#define X400_S_SUBJECT
Definition: x400_att.h:723
#define X400_N_NOTIFICATION_REQUEST
Definition: x400_att.h:676
int X400msTestSecurityEnv(struct X400msSession *sp)
Test the default Security Environment.
int X400msMsgAddStrParam(struct X400msMessage *mp, int paramtype, const char *value, size_t length)
Add string-valued parameter to the message.
#define X400_MSG_MESSAGE
Definition: x400_att.h:29
#define X400_E_NOMEMORY
Definition: x400_att.h:52
#define X400_E_SYSERROR
Definition: x400_att.h:49
#define X400_B_SEC_GEN_MOAC
Definition: x400_att.h:557
#define X400_S_OR_ADDRESS
Definition: x400_att.h:349
int X400msMsgDelete(struct X400msMessage *mp, int retain)
Delete message object.