examples/x400_mssend_rcv_sign.c

This is an example program which reads a messages and displays any information available on the signature.

/* Copyright (c) 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.
*
*/
/*
*
* 15.0a0-0
* 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 <x400_msapi.h>
#include <seclabel_api.h> /* For security labels */
#include <errno.h>
#include "example.h"
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:Z4U:L:";
/* 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;
const char* xml_filename = "seclabel.xml";
static int setup_msg_sec_env = 0;
int num_unsigned_rcvd;
int num_unverified_rcvd;
int num_verified_rcvd;
/* 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 get_msg(
struct X400msSession *sp
);
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 add_x411_label(
struct X400msMessage *mp, /* message object */
const char* xml_filename
);
static int add_4066_label(
struct X400msMessage *mp, /* message object */
const char* xml_filename
);
static int setup_msg_old_sec_env(
struct X400msMessage *mp, /* message object */
char *id,
char *dn,
char *pw
);
static int report_moac_info(
struct X400msMessage *mp
);
static void show_4406_certificate (struct X400msMessage *mp);
static void show_certificate (struct X400msMessage *mp);
static int report_4406_info(
struct X400msMessage *mp
);
static void print_sec_label(
char slab_buffer[],
unsigned int length
);
/* 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))
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);
}
printf("sending message 2\n");
status = submit_msg(orn, sp);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "Can't submit\n");
return (status);
}
printf("sending message 3\n");
status = submit_msg(orn, sp);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "Can't submit\n");
return (status);
}
/* now get a message */
status = get_msg(sp);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error in getting msg: %s\n",
X400msError(status));
exit(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);
}
/* 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, "x400msMsgAddStrParam returned error: %s\n",
X400msError (status));
return (status);
}
}
/* 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 eg by calling setup_msg_sec_env() above
*/
if (gen_4406_sig) {
printf("\nRequesting 4406 signature\n");
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msMsgAddStrParam returned error: %s\n", X400msError (status));
return (status);
}
/* add a security label */
printf("\nAdding 4406 label\n");
status = add_4066_label (mp, xml_filename);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "add_4406_label returned error: %s\n",
X400msError (status));
return (status);
}
} else {
printf("\nNot requesting 4406 signature\n");
}
if (need_x411_label) {
status = add_x411_label (mp, xml_filename);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "add_x411_label returned error: %s\n",
X400msError (status));
return (status);
}
} else {
printf("\nNot requesting X.411 Label\n");
}
status = X400msRecipNew (mp, X400_RECIP_STANDARD, &rp);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msRecipNew 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);
}
status = X400msMsgAddStrParam (mp, X400_S_SUBJECT, subject, -1);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msMsgAddStrParam 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);
}
/* 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);
}
/* 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 used to open the 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);
}
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 used to open the 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);
}
/* security additions */
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_4066_label(
struct X400msMessage *mp, /* message object */
const char* filename
)
{
#define XML_BUFSIZE 1024
#define STRING_BUFSIZE 1024
int status;
char xml_content[XML_BUFSIZE];
char str_content[STRING_BUFSIZE];
int str_len = STRING_BUFSIZE;
FILE *fd = NULL;
printf("Adding 4406 Security Label, using file %s\n", filename);
/* Read in the security label XML file */
fd = fopen(filename,"r");
if(fd == NULL) {
fprintf(stderr,"Failed to open %s : %s\n",
filename,strerror(errno));
}
fread(&xml_content,XML_BUFSIZE,1,fd);
fclose(fd);
status = SecLabelInit("Example program 2");
if (status != SECLABEL_E_NOERROR) {
fprintf(stderr, "SecLabelInit returned error %d\n", status);
}
/* Use SecLabelParse to turn the XML into an octet string */
status = SecLabelParse(xml_content,
str_content,
STRING_BUFSIZE,
&str_len);
if (status != SECLABEL_E_NOERROR) {
fprintf(stderr, "SecLabelParse returned error %d\n", status);
}
/* 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);
}
}
static int add_x411_label(
struct X400msMessage *mp, /* message object */
const char* filename
)
{
#define XML_BUFSIZE 1024
#define STRING_BUFSIZE 1024
int status;
char xml_content[XML_BUFSIZE];
char str_content[STRING_BUFSIZE];
int str_len = STRING_BUFSIZE;
FILE *fd = NULL;
printf("Adding X.411 Security Label, using file %s\n", filename);
/* Read in the security label XML file */
fd = fopen(filename,"r");
if(fd == NULL) {
fprintf(stderr,"Failed to open %s : %s\n",
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 octet string */
status = SecLabelParse(xml_content,
str_content,
STRING_BUFSIZE,
&str_len);
if (status != SECLABEL_E_NOERROR) {
fprintf(stderr, "SecLabelParse returned error %d\n", status);
}
/* 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);
}
}
static int get_msg(
struct X400msSession *sp
)
{
char buffer[BUFSIZ];
int status;
int nummsg;
int type;
int seqn;
struct X400msMessage *mp;
struct X400Recipient *rp;
int n;
size_t length;
int intparam;
char recipient_str[BUFSIZ];
printf("Waiting for new messages for 10 seconds\n");
status = X400msWait(sp, 10, &nummsg);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from Wait: %s\n", X400msError(status));
/* tidily close the session */
status = X400msClose(sp);
exit(status);
}
/* Set up the security environment.
*
* In R15.0 this need only be the name of a trusted certificate directory.
*
* Prior to R15.0, 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. NB even though we're not going to use our cert,
* (as we're going to use the cert in the message to check the MOAC
* we need to do this due to a limitation in the underlying X.509
* layer.
*/
/*
if (use_new_sec_env) {
setup_default_new_sec_env(sp, trusted_ca_certs_dir);
} else {
setup_default_old_sec_env(sp, security_id, identity_dn, passphrase);
}
*/
/* Turn off legacy bahaviour in which MOAC verification failure
* returns X400_E_NOERROR.
* We will now get X400_E_X509_VERIFY_FAILURE from MsgGet
* if/when the verification fails
*/
if (x400_default_recipient != NULL)
printf("Getting message\n");
status = X400msMsgGet(sp, 0, &mp, &type, &seqn);
switch (status) {
fprintf(stderr, "MsgGet successfully got message\n");
break;
default :
fprintf(stderr, "Error from MsgGet: %s\n", X400msError(status));
/* tidily close the session */
status = X400msClose(sp);
exit(status);
break;
}
if (type != X400_MSG_MESSAGE) {
fprintf(stderr, "Got a report (printing only some attributes)\n");
/* The ORADDRESS in the message is the (envelope) originator */
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from MsgGetStrParam: %s\n",
X400msError(status));
/* tidily close the session */
status = X400msClose(sp);
exit(status);
}
printf("Subject Identifier: %.*s\n", (int)length, buffer);
/* Get the primary recipients */
for (n = 1;; n++) {
status = X400msRecipGet(mp, X400_RECIP_REPORT, n, &rp);
if (status == X400_E_NO_RECIP)
break;
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from RecipGet: %s\n",
X400msError(status));
/* tidily close the session */
status = X400msClose(sp);
exit(status);
}
/* Note: recipient may not actually have an O/R address */
recipient_str,
sizeof recipient_str, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from RecipGetStrParam: %s\n",
X400msError(status));
/* tidily close the session */
status = X400msClose(sp);
exit(status);
}
/* print out the O/R Address of the report */
printf("Positive Delivery Report for recipient %d: %.*s\n", n,
(int)length, recipient_str);
/* The original message delivery time, if this attribute exists,
* then the report is a positive Delivery Report */
buffer, sizeof buffer, &length);
if (status == X400_E_NOERROR) {
/* Positive Delivery Report */
printf("Delivery Time: %.*s\n", (int)length, buffer);
}
else {
/* Negative Delivery Report */
printf("Negative Delivery Report for recipient %d: %s\n", n,
recipient_str);
/* Supplementary Info to the report */
buffer, sizeof buffer,
&length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from RecipGetStrParam: %s\n",
X400msError(status));
buffer[0] = '\0';
}
printf("Supplementary Info: %.*s\n", (int)length, buffer);
/* The reason why the message was not delivered */
status =
&intparam);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from MsgGetIntParam: %s\n",
X400msError(status));
}
printf("Non-Delivery Reason: %d\n", intparam);
/* The diagnostics of the report for this recipient */
status =
&intparam);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from MsgGetIntParam: %s\n",
X400msError(status));
}
printf("Non-Delivery Diagnostic: %d\n", intparam);
}
}
num_unsigned_rcvd++ ;
status = X400msMsgDelete(mp, 0);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from X400msMsgDelete: %s\n",
X400msError(status));
}
return (status);
}
/* x411 security label */
buffer, sizeof buffer, &length);
if (status == X400_E_NO_VALUE) {
printf("No X.411 security label\n");
} else if (status != X400_E_NOERROR) {
fprintf(stderr,"Failed to fetch X.411 security label: %d (%s)",
status, X400msError(status));
return (status);
} else {
fprintf(stderr, "X.411 Security Label returned OK (%d chars)\n",
(int)length);
print_sec_label(buffer, length);
}
/* report information about the MOAC in the message */
report_moac_info(mp);
/* report information about the 4406 in the message */
report_4406_info(mp);
/* The message identifier */
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from MsgGetStrParam: %s\n",
X400msError(status));
/* tidily close the session */
status = X400msClose(sp);
exit(status);
}
printf("Message Identifier: %.*s\n", (int)length, buffer);
/* The ORADDRESS in the message is the (envelope) originator */
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from MsgGetStrParam: %s\n",
X400msError(status));
/* tidily close the session */
status = X400msClose(sp);
exit(status);
}
printf("Originator: %.*s\n", (int)length, buffer);
/* Get the primary recipients */
for (n = 1;; n++) {
status = X400msRecipGet(mp, X400_RECIP_PRIMARY, n, &rp);
if (status == X400_E_NO_RECIP)
break;
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from RecipGet: %s\n", X400msError(status));
/* tidily close the session */
status = X400msClose(sp);
exit(status);
}
/* Note: recipient may not actually have an O/R address */
buffer, sizeof buffer, &length);
if (status == X400_E_NOERROR) {
printf("Recipient %d: %.*s\n", n, (int)length, buffer);
}
}
/* Subject is optional */
buffer, sizeof buffer, &length);
if (status == X400_E_NOERROR)
printf("Subject: %.*s\n", (int)length, buffer);
/* And message text (or it could be another type) */
buffer, sizeof buffer, &length);
if (status == X400_E_NOERROR)
printf("Text:\n%.*s\n", (int)length, buffer);
/* Deletes message in message store as well as internal copy */
status = X400msMsgDelete(mp, 0);
return status;
}
#ifdef notdef
/*
* Recommended function to setup security env for verification.
* No digitial ID required - just a directory which contains
* trust anchors which are read as DER file (certificate.crt).
*
* The certificate (containing public key) is obtained from the message
* which is referenced in the message.
*/
static void setup_default_new_sec_env(
struct X400msSession *sp,
char *trusted_ca_certs_dir
)
{
int status;
/* Directory containing trusted CA Certificates */
printf(" Adding %s as trusted CA cert dir\n", trusted_ca_certs_dir);
trusted_ca_certs_dir, -1);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "X400msSetStrDefault returned error: %s\n",
X400msError (status));
exit (status);
}
return;
}
/*
* Obsolete function to use to set up the security environment. This provides a
* directory in which PKCS12 files are checked to find one whose subject DN
* matches that of this client.
*
* Any self signed certificates found in the directory are treated as
* trusted.
*/
static void setup_default_old_sec_env(
struct X400msSession *sp,
char *id,
char *dn,
char *pw /* passphrase for private key in pkcs12 file */
)
{
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 */
/* X400msSetStrDefault(sp, X400_S_SEC_IDENTITY, "/var/isode/dsa-db/", -1);
* */
/* 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));
exit (status);
}
/* passphrase used to open the Identity */
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "X400msSetStrDefault returned error: %s\n",
X400msError (status));
exit (status);
}
return;
}
#endif
static int report_moac_info(
struct X400msMessage *mp
)
{
int status;
int intparam;
/* Check the MOAC */
status = X400msMsgGetIntParam(mp, X400_N_MOAC_STATUS, &intparam);
switch ( status ) {
num_unverified_rcvd++ ;
fprintf (stderr, "No MOAC in message\n");
break;
default:
num_unverified_rcvd++ ;
fprintf (stderr, "Unexpected error getting MOAC status: %s\n",
X400msError (status));
break;
fprintf (stderr, "Have MOAC in message (%d)\n", intparam);
switch (intparam) {
fprintf(stderr,
"MsgGet successfully verified signature in message\n");
show_certificate (mp);
fprintf(stderr, "continuing ...\n");
num_verified_rcvd++ ;
break;
fprintf(stderr,
"MOAC validation cannot take place because the security environment is invalid (%d):\n",
intparam);
/* other values will not be available */
break;
fprintf(stderr,
"MOAC validation cannot take place because the security environment is invalid (%d):\n",
intparam);
/* other values will not be available */
break;
fprintf(stderr, "Verification Error from MsgGet: %s\n",
X400msError(intparam));
show_certificate (mp);
fprintf(stderr, "continuing ...\n");
num_unverified_rcvd++ ;
break;
fprintf(stderr, "Verification Error from MsgGet: %s\n",
X400msError(intparam));
fprintf(stderr, "continuing ...\n");
num_unverified_rcvd++ ;
break;
fprintf(stderr, "Verification Error from MsgGet: %s\n",
X400msError(intparam));
show_certificate (mp);
fprintf(stderr, "continuing ...\n");
num_unverified_rcvd++ ;
break;
fprintf(stderr, "Verification Error from MsgGet: %s\n",
X400msError(intparam));
show_certificate (mp);
fprintf(stderr, "continuing ...\n");
num_unverified_rcvd++ ;
break;
fprintf(stderr, "Verification Error from MsgGet: %s\n",
X400msError(intparam));
show_certificate (mp);
fprintf(stderr, "continuing ...\n");
num_unverified_rcvd++ ;
break;
fprintf(stderr, "Verification Error from MsgGet: %s\n",
X400msError(intparam));
show_certificate (mp);
fprintf(stderr, "continuing ...\n");
num_unverified_rcvd++ ;
break;
fprintf(stderr, "Verification Error from MsgGet: %s\n",
X400msError(intparam));
show_certificate (mp);
fprintf(stderr, "continuing ...\n");
num_unverified_rcvd++ ;
break;
default :
fprintf(stderr, "Unexpected verification error from MsgGet: %s\n",
X400msError(intparam));
show_certificate (mp);
fprintf(stderr, "continuing ...\n");
num_unverified_rcvd++ ;
break;
}
}
}
static int report_4406_info(
struct X400msMessage *mp
)
{
int status;
int intparam;
size_t length;
char buffer[BUFSIZ];
/* Check the 4406 signatures */
status = X400msMsgGetIntParam(mp, X400_N_S4406_STATUS, &intparam);
switch ( status ) {
num_unverified_rcvd++ ;
fprintf (stderr, "No 4406 signature in message\n");
default:
num_unverified_rcvd++ ;
fprintf (stderr, "Unexpected error getting 4406 signature status: %s\n",
X400msError (status));
break;
fprintf (stderr, "Have 4406 signature in message (%d)\n", intparam);
switch (intparam) {
fprintf(stderr,
"MsgGet successfully verified signature in message\n");
show_4406_certificate (mp);
fprintf(stderr, "continuing ...\n");
num_verified_rcvd++ ;
break;
fprintf(stderr,
"4406 signature validation cannot take place because the security environment is invalid (%d):\n",
intparam);
/* other values will not be available */
break;
fprintf(stderr,
"4406 signature validation cannot take place because the security environment is invalid (%d):\n",
intparam);
/* other values will not be available */
break;
fprintf(stderr, "Verification Error from MsgGet: %s\n",
X400msError(intparam));
show_4406_certificate (mp);
fprintf(stderr, "continuing ...\n");
num_unverified_rcvd++ ;
break;
fprintf(stderr, "Verification Error from MsgGet: %s\n",
X400msError(intparam));
fprintf(stderr, "continuing ...\n");
num_unverified_rcvd++ ;
break;
fprintf(stderr, "Verification Error from MsgGet: %s\n",
X400msError(intparam));
show_4406_certificate (mp);
fprintf(stderr, "continuing ...\n");
num_unverified_rcvd++ ;
break;
fprintf(stderr, "Verification Error from MsgGet: %s\n",
X400msError(intparam));
show_4406_certificate (mp);
fprintf(stderr, "continuing ...\n");
num_unverified_rcvd++ ;
break;
fprintf(stderr, "Verification Error from MsgGet: %s\n",
X400msError(intparam));
show_4406_certificate (mp);
fprintf(stderr, "continuing ...\n");
num_unverified_rcvd++ ;
break;
fprintf(stderr, "Verification Error from MsgGet: %s\n",
X400msError(intparam));
show_4406_certificate (mp);
fprintf(stderr, "continuing ...\n");
num_unverified_rcvd++ ;
break;
fprintf(stderr, "Verification Error from MsgGet: %s\n",
X400msError(intparam));
show_4406_certificate (mp);
fprintf(stderr, "continuing ...\n");
num_unverified_rcvd++ ;
break;
default :
fprintf(stderr, "Unexpected verification error from MsgGet: %s\n",
X400msError(intparam));
show_4406_certificate (mp);
fprintf(stderr, "continuing ...\n");
num_unverified_rcvd++ ;
break;
}
}
/* 4406 security label */
buffer, sizeof buffer, &length);
if (status == X400_E_NO_VALUE) {
printf("No 4406 security label\n");
} else if (status != X400_E_NOERROR) {
fprintf(stderr,"Failed to fetch 4406 security label: %d (%s)",
status, X400msError(status));
return (status);
} else {
fprintf(stderr, "4406 Security Label returned OK (%d chars)\n",
(int)length);
print_sec_label(buffer, length);
}
/* 4406 signing time */
buffer, sizeof buffer, &length);
if (status == X400_E_NOERROR)
printf("4406 signing time returned OK\n%.*s\n", (int)length, buffer);
else
printf("4406 signing time not returned (%d) (%s)\n", status,
X400msError(status));
}
static void print_sec_label(
char slab_buffer[],
unsigned int length
)
{
char xml_buffer[XML_BUFSIZE];
int status;
status = SecLabelInit("Example program");
if (status != SECLABEL_E_NOERROR) {
fprintf(stderr, "SecLabelInit returned error %d\n", status);
return ;
}
status = SecLabelPrint((const unsigned char *) slab_buffer,
length,
xml_buffer,
XML_BUFSIZE);
if (status != SECLABEL_E_NOERROR) {
fprintf(stderr, "SecLabelParse returned error %d\n", status);
return ;
}
/* You could now write out the XML file, or parse it in memory..*/
printf("Got security label:%s\n", xml_buffer);
return;
}
static void show_certificate (struct X400msMessage *mp)
{
int status;
struct X400Certificate *cert;
char buffer[BUFSIZ];
size_t length;
int paramval;
status = X400msMsgGetCert (mp, X400_N_CERT_MOAC, &cert);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "Error getting MOAC certificate: %s\n",
X400msError (status));
return;
}
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from CertGetStrParam: %s\n",
X400msError(status));
return;
}
fprintf(stderr,
"subject DN of originator certificate '%.*s'\n", (int)length, buffer);
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from CertGetStrParam: %s\n",
X400msError(status));
return;
}
fprintf(stderr,
"issuer DN of originator certificate '%.*s'\n", (int)length, buffer);
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
if ( status == X400_E_NO_VALUE ) {
fprintf(stderr, "No ORaddress subject alt. name\n");
} else {
fprintf(stderr, "Error from CertGetStrParam: %s\n",
X400msError(status));
return;
}
} else {
fprintf(stderr, "ORaddress subject alt name: '%.*s'\n", (int)length, buffer);
}
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from CertGetStrParam: %s\n",
X400msError(status));
return;
}
fprintf(stderr, "ORaddress subject alt name status: %s\n",
X400msError (paramval));
}
static void show_4406_certificate (struct X400msMessage *mp)
{
int status;
struct X400Certificate *cert;
char buffer[BUFSIZ];
size_t length;
int paramval;
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "Error getting 4406 certificate: %s\n",
X400msError (status));
return;
}
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from CertGetStrParam: %s\n",
X400msError(status));
return;
}
fprintf(stderr, "subject DN of originator certificate '%.*s'\n",
(int)length, buffer);
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from CertGetStrParam: %s\n",
X400msError(status));
return;
}
fprintf(stderr, "issuer DN of originator certificate '%.*s'\n",
(int)length, buffer);
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
if ( status == X400_E_NO_VALUE ) {
fprintf(stderr, "No ORaddress subject alt. name\n");
} else {
fprintf(stderr, "Error from CertGetStrParam: %s\n",
X400msError(status));
return;
}
} else {
fprintf(stderr, "ORaddress subject alt name: '%.*s'\n",
(int)length, buffer);
}
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from CertGetStrParam: %s\n",
X400msError(status));
return;
}
fprintf(stderr, "ORaddress subject alt name status: %s\n",
X400msError (paramval));
return;
}
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 : Priority (0 - normal, 1 - non-urgent, 2 - urgent \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 -4 : Generate STANAG 4406 PCT Signatures\n");
return;
}