examples/x400_mssend_sign.c

This is an example program which submits a message either indirectly via the P7 Message Store or directly to the MTA's P3 responder. This program will attempt to sign a message using a security environment be present in SHAREDIR/x509. This is installed by default.

/* Copyright (c) 2003-2014, Isode Limited, London, England.
* All rights reserved.
*
* Acquisition and use of this software and related materials for any
* purpose requires a written licence agreement from Isode Limited,
* or a written licence from an organisation licenced by Isode Limited
* to grant such a licence.
*
*/
/*
*
* @VERSION@
* Simple example program for submitting a message via a message store.
* The security environment is set up so that messages are signed.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <x400_msapi.h>
#include <seclabel_api.h> /* For security labels */
#include "example.h"
#include "ms_example.h"
#include "time.h"
#define PCT_OID "1.2.840.113549.1.9.16.1.6"
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:S:Y:Z4B:F:N:";
/* These are the data items used to construct the message for submission */
static char *default_recip = "/CN=lppt1/OU=lppt/O=attlee/PRMD=TestPRMD/ADMD=TestADMD/C=GB/";
char *recip;
static char *content_id = "030924.140212";
static const char text[] = "First line\r\nSecond line\r\n";
static char *binary_data;
static int setup_msg_sec_env = 0;
/* set this to non zero to cause the IA5 body part to be an attachment */
int send_ia5_as_att = 0;
/* local functions */
static void usage(void) ;
static int send_msg(
int contype,
char *orn,
char *def_dn,
char *pa,
char *password);
static int submit_msg(
char *orn,
struct X400msSession *sp /* session object */
);
static int setup_default_new_sec_env(
struct X400msSession *sp,
char *identity_filename,
char *pw
);
static int setup_default_old_sec_env(
struct X400msSession *sp,
char *id,
char *dn,
char *pw
);
static int setup_msg_new_sec_env(
struct X400msMessage *mp, /* message object */
char *identity_filename,
char *pw
);
static int setup_msg_old_sec_env(
struct X400msMessage *mp, /* message object */
char *id,
char *dn,
char *pw
);
static int add_sec_label(
struct X400msMessage *mp /* message object */
);
static int add_content(
struct X400msMessage *mp /* message object */
);
/* start here */
int main (
int argc,
char **argv
)
{
char pa[BUFSIZ];
char orn[BUFSIZ];
char *def_oraddr;
char *def_dn;
char *def_pa;
int contype;
int status;
char password[BUFSIZ];
if (get_args(argc, argv, optstr)) {
usage();
exit(-1);
}
printf("Connection type (0 = P7, 1 = P3 submit only, 2 = P3 both directions) [%d]: ", x400_contype);
contype = ic_fgetc(x400_contype, stdin);
if (contype != 10)
ic_fgetc(x400_contype, stdin);
if ( contype < '0' || '2' < contype )
contype = x400_contype;
else
contype -= '0';
if (contype == 0) {
def_oraddr = x400_ms_user_addr;
def_dn = x400_ms_user_dn;
def_pa = x400_ms_presentation_address;
} else {
def_oraddr = x400_mta_user_addr;
def_dn = x400_mta_user_dn;
def_pa = x400_mta_presentation_address;
}
printf("Your ORAddress [%s] > ", def_oraddr);
ic_fgets (orn, sizeof orn, stdin);
if ( orn[strlen(orn)-1] == '\n' )
orn[strlen(orn)-1] = '\0';
if (orn[0] == '\0')
strcpy(orn, def_oraddr);
/* Prompt for password; note: reflected. */
printf ("Password [%s]: ",
contype == 0 ? x400_p7_password : x400_p3_password);
if ( ic_fgets (password, sizeof password, stdin) == NULL )
exit (1);
if (password[strlen(password)-1] == '\n' )
password[strlen(password)-1] = '\0';
if (password[0] == '\0')
strcpy(password, contype == 0 ? x400_p7_password : x400_p3_password);
/* Presentation Address */
printf("Presentation Address [%s] > ", def_pa);
ic_fgets (pa, sizeof pa, stdin);
if ( pa[strlen(pa)-1] == '\n' )
pa[strlen(pa)-1] = '\0';
if (pa[0] == '\0')
strcpy(pa, def_pa);
printf("sending message using session 1\n");
if ((status = send_msg(contype, orn, def_dn, pa, password))
fprintf (stderr, "Error in sending message\n");
exit (status);
}
/*
printf("sending message using session 2\n");
if ((status = send_msg(contype, orn, def_dn, pa, password))
!= X400_E_NOERROR ) {
fprintf (stderr, "Error sending message\n");
exit (status);
}
*/
return (status);
}
static int send_msg(
int contype,
char *orn,
char *def_dn,
char *pa,
char *password
)
{
struct X400msSession *sp; /* session object */
int status;
/* we've got what we need - now open an API session */
status = X400msOpen (contype, orn, def_dn, password, pa, NULL, &sp);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "Error in Open: %s\n", X400msError (status));
fprintf (stderr, "%s %s %s\n", orn, def_dn, pa);
return (status);
}
/* setup logging */
/* Set up the security environment.
*
* The security env can be specified the new way (recommended) using
* a PKCS12 filename and passphrase, or as a directory (deprecated and
* obsolete).
*
* If the ID is specified as a directory, in which the subdirectory
* "x509" is expected to contain one or more PKCS12 files.
* The appropriate Digital Identity is determined from the
* DN of the subject, and the passphrase is used to decrypt
* the private key.
*/
if (use_new_sec_env) {
status = setup_default_new_sec_env(sp, identity_filename, passphrase);
} else {
status = setup_default_old_sec_env(sp, security_id, identity_dn,
passphrase);
}
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "Can't setup security environment\n");
return (status);
}
printf("sending message 1\n");
status = submit_msg(orn, sp);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "Can't submit\n");
return (status);
}
status = X400msClose (sp);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "X400msClose returned error: %s\n", X400msError (status));
return (status);
}
return status;
}
static int submit_msg(
char *orn,
struct X400msSession *sp /* session object */
)
{
struct X400msMessage *mp; /* message object */
struct X400Recipient *rp; /* recipient object */
char tmp[BUFSIZ];
FILE *fp = NULL;
int fs=0;
int status;
if (x400_default_recipient != NULL)
recip = x400_default_recipient;
else
recip = default_recip;
printf("Message recipient [%s]: ", recip);
ic_fgets (tmp, sizeof tmp, stdin);
if ( tmp[strlen(tmp)-1] == '\n' )
tmp[strlen(tmp)-1] = '\0';
if (strlen(tmp) != 0)
recip = strdup(tmp);
printf("Subject [%s]: ", subject);
ic_fgets (tmp, sizeof tmp, stdin);
if ( tmp[strlen(tmp)-1] == '\n' )
tmp[strlen(tmp)-1] = '\0';
if (strlen(tmp) != 0)
subject = strdup(tmp);
status = X400msMsgNew (sp, X400_MSG_MESSAGE, &mp);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msMsgNew returned error: %s\n", X400msError (status));
return (status);
}
printf("\n\nPreparing Message\n");
/* set content type */
if (x400_default_external_content_type != NULL) {
printf("Sending external content type %s\n",
x400_default_external_content_type);
x400_default_external_content_type, -1);
} else {
printf("Sending content type %d\n", x400_default_content_type);
x400_default_content_type);
}
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "X400msMsgAddIntParam returned error: %s\n",
X400msError (status));
return (status);
}
/* Set up the security environment for this message overriding the
* default security env.
*
* The security env can be specified the new way (recommended) using
* a PKCS12 filename and passphrase, or as a directory (deprecated and
* obsolete).
*
* If the ID is specified as a pathname, in which the subdirectory
* "x509" is expected to contain one or more PKCS12 files.
* The appropriate Digital Identity is determined from the
* DN of the subject, and the passphrase is used to decrypt
* the private key.
*/
if (setup_msg_sec_env) {
if (use_new_sec_env) {
status = setup_msg_new_sec_env(mp, identity_filename, passphrase);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "Can't setup new security environment\n");
return (status);
}
} else {
status = setup_msg_old_sec_env(mp, security_id, identity_dn2,
passphrase);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "Can't setup old security environment\n");
return (status);
}
}
}
/* Instruct the X400msMsgSend() function to generate a MOAC (signature) for
* the message.
*
* The default attributes will be used unless the attributes are
* also included in the message eg by calling setup_msg_sec_env() above
*/
if (gen_moac) {
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msMsgAddIntParam returned error: %s\n",
X400msError (status));
return (status);
}
}
if (gen_4406_sig) {
/* Instruct the X400msMsgSend() function to generate a STANAG 4406
* signature for the message
*
* The default attributes will be used unless the attributes are
* also included in the message
* e.g. by calling setup_msg_sec_env() above
*/
printf("\nRequesting 4406 signature\n");
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msMsgAddIntParam returned error: %s\n",
X400msError (status));
return (status);
}
/* set the external content type correctly to PCT */
PCT_OID, -1);
printf("Sending external content type %s\n", PCT_OID);
} else {
printf("\nNot requesting 4406 signature\n");
}
status = add_sec_label (mp);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "Failed to add 4406 Security Label: %s\n",
X400msError (status));
return (status);
}
status = X400msRecipNew (mp, X400_RECIP_STANDARD, &rp);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msRecipNew returned error: %s\n", X400msError (status));
return (status);
}
/* put precedence extension into primary recipient */
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msRecipAddIntParam returned error: %s\n",
X400msError (status));
return (status);
}
status = X400msRecipAddStrParam (rp, X400_S_OR_ADDRESS, recip, -1);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msRecipAddStrParam returned error: %s\n", X400msError (status));
return (status);
}
status = X400msRecipAddStrParam (rp, X400_S_DIRECTORY_NAME, "CN=recipient;c=gb", -1);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msRecipAddStrParam returned error: %s\n", X400msError (status));
return (status);
}
status = X400msMsgAddStrParam (mp, X400_S_OR_ADDRESS, orn, -1);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n", X400msError (status));
return (status);
}
status = X400msMsgAddStrParam (mp, X400_S_DIRECTORY_NAME, "CN=originator;c=gb", -1);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n", X400msError (status));
return (status);
}
/* Ask for +ve and -ve delivery reports */
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msRecipAddStrParam returned error: %s\n", X400msError (status));
return (status);
}
/* Ask for +ve and -ve read receipts */
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msRecipAddStrParam returned error: %s\n", X400msError (status));
return (status);
}
content_id, -1);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n", X400msError (status));
return (status);
}
/* subject */
{
time_t t;
time(&t);
char tmp_buffer[255];
// NB strip newline from ctime result
snprintf(tmp_buffer, 244, "%s '%s' '%.19s'",
subject, get_x400_pty_str_from_4406(x400_default_priority), ctime(&t));
printf("Subject is '%s'\n", tmp_buffer);
status = X400msMsgAddStrParam (mp, X400_S_SUBJECT, tmp_buffer, -1);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n",
X400msError (status));
exit (status);
}
}
/* put FLOT into IA5 BP */
if (flot_string != NULL) {
status = X400msMsgAddStrParam (mp, X400_T_IA5TEXT, flot_string, -1);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400ms returned error: %s\n",
X400msError (status));
return (status);
}
printf("Sent IA5 FLOT:\n%s\n", flot_string);
}
if (add_content(mp) != X400_E_NOERROR) {
fprintf (stderr, "add_content() returned error: %s\n",
X400msError (status));
return (status);
}
status = X400msMsgAddStrParam (mp, X400_T_ISO8859_1, text, -1);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400ms returned error: %s\n", X400msError (status));
return (status);
}
printf("Sent 8859 content:\n%s\n", text);
/* now an IA5 body part using the bodypart func */
status = X400msMsgAddAttachment (mp, X400_T_IA5TEXT, text, strlen(text));
if ( status != X400_E_NOERROR ) {
printf("failed to add X400_T_IA5TEXT BP\n");
return (status);
}
printf("Sent IA5 content:\n%s\n", text);
/* or a Binary body part using the bodypart func */
if (filename_to_send != NULL) {
binary_data = (char *) malloc(100000);
if ( binary_data == NULL )
fp = fopen(filename_to_send, "r");
if (fp == (FILE *)NULL) {
printf("Cannot open binary file\n");
return (X400_E_SYSERROR);
}
if ((fs = fread (binary_data, sizeof(char), 100000/sizeof(char), fp) ) == -1) {
printf("Cannot read from binary file\n");
return (X400_E_SYSERROR);
}
fclose(fp);
status = X400msMsgAddAttachment (mp, X400_T_BINARY, binary_data, fs);
if ( status != X400_E_NOERROR ) {
printf("failed to add X400_T_BINARY BP\n");
return (status);
}
} else {
printf("no binary file set - not sending X400_T_BINARY\n");
}
status = X400msMsgSend (mp);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msMsgSend returned error: %s\n", X400msError (status));
return (status);
} else {
printf("Message submitted successfully\n");
}
status = X400msMsgDelete (mp, 0);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msMsgDelete returned error: %s\n", X400msError (status));
return (status);
}
mp = NULL;
rp = NULL;
return (status);
}
static int setup_default_new_sec_env(
struct X400msSession *sp,
char *identity,
char *pw
)
{
int status;
/* Filename of the Digital Identity (PKCS12 file) */
identity, -1);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "X400msSetStrDefault returned error: %s\n",
X400msError (status));
return (status);
}
/* Passphrase of the private key in the above Digital Identity */
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "X400msSetStrDefault returned error: %s\n",
X400msError (status));
return (status);
}
/* test the sec env */
status = X400msTestSecurityEnv (sp);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "X400msTestSecurityEnv returned error: %s\n",
X400msError (status));
return (status);
}
printf ("X400msTestSecurityEnv returned success\n");
return status;
}
static int setup_default_old_sec_env(
struct X400msSession *sp,
char *id,
char *dn,
char *pw
)
{
int status;
/* first set a default security identity. This passes in the name of a
* directory, which contains an x509 subdirectory in which all Identities
* are held */
/* select by DN which Identity is to be used (if there are several)
* Currently these must be PKCS12 files */
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "X400msSetStrDefault returned error: %s\n",
X400msError (status));
return (status);
}
/* Passphrase of the private key in the above Digital Identity */
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "X400msSetStrDefault returned error: %s\n",
X400msError (status));
return (status);
}
return status;
}
static int setup_msg_new_sec_env(
struct X400msMessage *mp, /* message object */
char *identity,
char *pw
)
{
int status;
/* Filename of the Digital Identity (PKCS12 file) */
identity, -1);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "X400msMsgAddStrParam returned error: %s\n",
X400msError (status));
return (status);
}
/* Passphrase of the private key in the above Digital Identity */
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n",
X400msError (status));
return (status);
}
return (status);
}
static int setup_msg_old_sec_env(
struct X400msMessage *mp, /* message object */
char *id,
char *dn,
char *pw
)
{
int status;
/* overide the default security environment by specifying a new set of
* attibutes, and put them into the message */
/* security additions */
status = X400msMsgAddStrParam (mp, X400_S_SEC_IDENTITY, id, -1);
/* status = X400msMsgAddStrParam (mp, X400_S_SEC_IDENTITY, "/var/isode/dsa-db", -1); */
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n",
X400msError (status));
return (status);
}
/* security additions */
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n",
X400msError (status));
return (status);
}
/* security additions */
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n",
X400msError (status));
return (status);
}
return (status);
}
static int add_sec_label(
struct X400msMessage *mp /* message object */
)
{
#define XML_BUFSIZE 1024
#define STRING_BUFSIZE 1024
const char* xml_filename = "seclabel.xml";
char xml_content[XML_BUFSIZE];
char xml_content_inserted[XML_BUFSIZE];
char str_content[STRING_BUFSIZE];
int str_len = STRING_BUFSIZE;
FILE *fd = NULL;
int status;
/* Read in the security label XML file */
fd = fopen(xml_filename,"r");
if(fd == NULL) {
fprintf(stderr,"Failed to open %s : %s\n",
xml_filename,strerror(errno));
}
fread(&xml_content,XML_BUFSIZE,1,fd);
fclose(fd);
status = SecLabelInit("Example program");
if (status != SECLABEL_E_NOERROR) {
fprintf(stderr, "SecLabelInit returned error %d\n", status);
}
/* Use SecLabelParse to turn the XML into an octect string */
status = SecLabelParse(xml_content,
str_content,
STRING_BUFSIZE,
&str_len);
if (status != SECLABEL_E_NOERROR) {
fprintf(stderr, "SecLabelParse returned error %d\n", status);
}
if ((gen_4406_sig) && (send_4406_label)) {
/* Insert into the CMS signature */
/* Add the octet string to the message pointer */
str_content,str_len);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n",
X400msError (status));
return (status);
}
}
if (send_x411_label) {
/* Insert into the envelope */
/* Add the octet string to the message pointer */
str_content,str_len);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n",
X400msError (status));
return (status);
}
} else {
printf("\nNot requesting X.411 Label\n");
}
/* check what we inserted */
(void) SecLabelPrint((const unsigned char *)str_content,
str_len,
xml_content_inserted,
XML_BUFSIZE);
/* write out the XML we read from file and inserted ..*/
if (send_x411_label) {
printf("Added this X.411 security label:%s\n", xml_content);
} else {
printf("Not adding X.411 security label\n");
}
if ((gen_4406_sig) && (send_4406_label)) {
printf("Added this 4406 security label:%s\n", xml_content_inserted);
} else {
printf("Not adding 4406 security label\n");
}
}
static int add_content(
struct X400msMessage *mp /* message object */
)
{
FILE *fp = NULL;
int fs = 0;
int status;
/* add some attachments/body parts
* Strictly a message simply has a sequence of body parts.
* However in human terms, it can be useful to treat the Body Parts
* as
* - text, i.e. an IA5 or general text attachment
* - followed by 0 or more attachments (e.g. documents, images etc)
*
* The API allows for either style.
*
* Use the AddStrParam() function to add a text attachment
* Use the X400msMsgAddAttachment() function to add a Body Part
* Use the X400msMsgAddMessageBodyWType() function to add structured
* Body Part (e.g. message, FTBP)
*/
status = X400msMsgAddStrParam (mp, X400_T_ISO8859_1, text, -1);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400ms returned error: %s\n", X400msError (status));
return (status);
}
printf("Sent 8859 attachment as string:\n%s\n", text);
if (send_ia5_as_att) {
/* now an IA5 body attachment using the attachment func */
text, strlen(text));
if ( status != X400_E_NOERROR ) {
printf("failed to add X400_T_IA5TEXT attachment\n");
return (status);
}
printf("Sent IA5 as first attachment:\n%s\n", text);
} else {
/* now an IA5 attachment using the str func */
status = X400msMsgAddStrParam (mp, X400_T_IA5TEXT, text, -1);
if ( status != X400_E_NOERROR ) {
printf("failed to add X400_T_IA5TEXT BP\n");
return (status);
}
printf("Sent IA5 as string in message \n%s\n", text);
}
/* now an 8859-1 body attachment using the attachment func */
status = X400msMsgAddAttachment (mp, X400_T_ISO8859_1, text, strlen(text));
if ( status != X400_E_NOERROR ) {
printf("failed to add X400_T_ISO8859_1, attachment\n");
return (status);
}
printf("Sent 8859-1 as attachment:\n%s\n", text);
/* or a Binary body part using the bodypart func */
if (filename_to_send != NULL) {
binary_data = (char *) malloc(100000);
if ( binary_data == NULL )
fp = fopen(filename_to_send, "r");
if (fp == (FILE *)NULL) {
printf("Cannot open binary file\n");
return (X400_E_SYSERROR);
}
if ((fs = fread (binary_data, sizeof(char), 100000/sizeof(char), fp))
== -1) {
printf("Cannot read from binary file\n");
return (X400_E_SYSERROR);
}
fclose(fp);
status = X400msMsgAddAttachment (mp, X400_T_BINARY, binary_data, fs);
if ( status != X400_E_NOERROR ) {
printf("failed to add X400_T_BINARY BP\n");
return (status);
}
free (binary_data);
} else {
printf("no binary file set - not sending X400_T_BINARY\n");
}
return status;
}
static void usage(void) {
printf("usage: %s\n", optstr);
printf("\t where:\n");
printf("\t -u : Don't prompt to override defaults \n");
printf("\t -3 : Use P3 connection \n");
printf("\t -7 : Use P7 connection \n");
printf("\t -m : OR Address in P7 bind arg \n");
printf("\t -d : DN in P7 bind arg \n");
printf("\t -p : Presentation Address of P7 Store \n");
printf("\t -w : P7 password of P7 user \n");
printf("\t -M : OR Address in P3 bind arg \n");
printf("\t -D : DN in P3 bind arg \n");
printf("\t -P : Presentation Address of P3 server\n");
printf("\t -W : P3 password of P3 user \n");
printf("\t -o : Originator \n");
printf("\t -O : Originator Return Address \n");
printf("\t -r : Recipient\n");
printf("\t -l : Logline\n");
printf("\t -y : Military Priority \n");
printf("\t\t 0 - deferred, 1 - routine, 2 - priority \n");
printf("\t\t 3 - immediate, 4 - flash, 5 - override \n");
printf("\t -C : Content Type (2/22/772/OID) \n");
printf("\t -i : Implicit conversion prohibited = TRUE \n");
printf("\t -a : Alternate Recipient Prohibited = TRUE \n");
printf("\t -q : Content Return Request = TRUE \n");
printf("\t -s : Disclosure of Recipient = FALSE \n");
printf("\t -A : Recipient Reassignment Prohibited = FALSE \n");
printf("\t -v : Conversion with Loss Prohibited = FALSE \n");
printf("\t -e : Security Environment (dir with x509 subdir): obsolete, use -Y <p12file>\n");
printf("\t -x : DN of X.509 Digital Identity\n");
printf("\t -b : Passphrase for private key in PKCS12 file\n");
printf("\t -f : Filename to transfer as binary bp\n");
printf("\t -Y : Filename of PKCS12 file containing Digital Identity\n");
printf("\t -Z : Generate MOAC Signature\n");
printf("\t -4 : Generate STANAG 4406 PCT Signatures\n");
printf("\t -B : Subject of message\n");
printf("\t -F : String to insert in first line of text (e.g. as FLOT)\n");
printf("\t -N : Insert Security Label in (e)nvelope or (4)406 signature\n");
return;
}