MS X.400 API
examples/x400_msrcv_msg_tok_sign.c
This is an example program which submits a signed message.
/* Copyright (c) 2009-2024, 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 receiving a message from a store.
* The security environment is set up so that signed messages
* will have per message MOAC signatures and recipient Message Token
* signatures verified.
*
* Note that a valid Digital Identity is no longer required in order to
* perform verification. Instead the name of a directory containing trusted,
* self signed certificates in DER form can be passed in.
*/
#include <stdio.h>
#include <stdlib.h>
#include <x400_msapi.h>
#include "example.h"
#include "ms_example.h"
#include <seclabel_api.h> /* For security labels */
#include <isode/base/compat.h>
#define XML_BUFSIZE 1024
int num_unsigned_rcvd;
int num_unverified_rcvd;
int num_verified_rcvd;
int num_messages_rcvd ;
int num_reports_rcvd ;
int num_ipns_rcvd ;
static char *optstr = "u37m:d:p:w:M:D:P:W:e:b:x:EY:U:I";
static void usage(void);
static int get_msg(
struct X400msSession *sp
);
static void setup_default_new_sec_env(
struct X400msSession *sp,
char *sec_trusted_cert_dir
);
static void setup_default_old_sec_env(
struct X400msSession *sp,
char *id,
char *dn,
char *pw /* passphrase for private key in pkcs12 file */
);
static void report_msg_token_info(
struct X400Recipient *rp
);
static int get_sec_label(
struct X400msMessage *mp
);
static void print_sec_label(
unsigned char slab_buffer[],
unsigned int length
);
static int get_cic(
struct X400Recipient *rp
);
static int get_4406_info(
struct X400msMessage *mp
);
static void show_recip_certificate (
struct X400Recipient *rp,
int certtype,
const char *tag);
static void show_message_certificate (
struct X400msMessage *mp,
const char *tag);
static void show_certificate (
struct X400Certificate *cert,
const char *tag);
static int handle_ipn(
struct X400msMessage *mp
);
static int handle_msg(
struct X400msSession *sp,
struct X400msMessage *mp
);
static int send_ipn(
struct X400msSession *sp,
struct X400msMessage *mp,
struct X400msMessage **ipn
);
static int do_report(
struct X400msSession *sp,
struct X400msMessage *mp
);
int
main(
int argc,
char **argv)
{
char buffer[BUFSIZ];
char pa[BUFSIZ];
char orn[BUFSIZ];
int status;
int nummsg;
struct X400msSession *sp;
int contype;
char *def_oraddr;
char *def_dn;
char *def_pa;
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(buffer, sizeof buffer, stdin) == NULL)
exit(1);
if (buffer[strlen(buffer) - 1] == '\n')
buffer[strlen(buffer) - 1] = '\0';
if (buffer[0] == '\0')
strcpy(buffer, contype == 0 ? x400_p7_password : x400_p3_password);
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);
status = X400msOpen(contype, orn, def_dn, buffer, pa, &nummsg, &sp);
exit(status);
}
/* setup logging from $(ETCDIR)x400api.xml or $(SHAREDIR)x400api.xml */
if (nummsg == 0) {
printf ("no messages - waiting for a message to be delivered.....\n");
}
else {
printf("%d messages waiting\n", nummsg);
}
status = get_msg(sp);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error in getting msg: %s\n",
X400msError(status));
exit(status);
}
fprintf(stderr, "got first\n");
do {
fprintf(stderr, "================================================\n");
status = get_msg(sp);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error in getting msg: %s\n",
X400msError(status));
exit(status);
}
} while (until_no_more_msgs);
status = X400msClose(sp);
printf("%d num_messages_rcvd\n", num_messages_rcvd);
printf("%d num_reports_rcvd\n", num_reports_rcvd);
printf("%d num_unsigned_rcvd\n", num_unsigned_rcvd);
printf("%d num_unverified_rcvd\n", num_unverified_rcvd);
printf("%d num_verified_rcvd\n", num_verified_rcvd);
printf("%d num_ipns_rcvd\n", num_ipns_rcvd);
return(status);
}
static int get_msg(
struct X400msSession *sp
)
{
int status;
int nummsg;
int type;
int seqn;
struct X400msMessage *mp;
int intparam;
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);
printf("%d num_messagese_rcvd\n", num_messages_rcvd);
printf("%d num_reports_rcvd\n", num_reports_rcvd);
printf("%d num_unsigned_rcvd\n", num_unsigned_rcvd);
printf("%d num_unverified_rcvd\n", num_unverified_rcvd);
printf("%d num_verified_rcvd\n", num_verified_rcvd);
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
*/
printf("Getting message\n");
status = X400msMsgGet(sp, 0, &mp, &type, &seqn);
switch (status) {
case X400_E_NOERROR:
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;
}
/**********************************/
/* Report on the received Report */
/**********************************/
status = do_report(sp, mp);
return (status);
}
/**********************************/
/* Report on the received Message */
/**********************************/
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from MsgGetIntParam (X400_N_IS_IPN): %s\n",
X400msError(status));
} else {
printf("Type of Message: %d\n", intparam);
if (intparam != 0) {
/**********************************/
/* Report on the received IPN */
/**********************************/
printf("Received an IPN\n");
num_ipns_rcvd++;
handle_ipn(mp);
status = X400msMsgDelete(mp, 0);
return status;
}
}
/* we have received a message */
num_messages_rcvd++ ;
status = handle_msg(sp, mp);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from handle_msg: %s\n",
X400msError(status));
return status;
}
if (gen_ipn) {
struct X400msMessage *ipn;
status = send_ipn(sp, mp, &ipn);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from send_ipn: %s\n",
X400msError(status));
}
/* Deletes message in message store as well as internal copy */
status = X400msMsgDelete(mp, 0);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from X400msMsgDelete (subject message)%s\n",
X400msError(status));
}
status = X400msMsgDelete(ipn, 0);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from X400msMsgDelete (IPN)%s\n",
X400msError(status));
}
return status;
} else {
/* Deletes message in message store as well as internal copy */
status = X400msMsgDelete(mp, 0);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from X400msMsgDelete (IPN)%s\n",
X400msError(status));
}
return status;
}
return X400_E_NOERROR;
}
static int do_report(
struct X400msSession *sp,
struct X400msMessage *mp
)
{
char buffer[BUFSIZ];
size_t length;
int intparam;
char recipient_str[BUFSIZ];
int status;
int n;
struct X400Recipient *rp;
/**********************************/
/* Report on the received Report */
/**********************************/
num_reports_rcvd++ ;
fprintf(stderr, "Got a report (printing only some attributes)\n");
/* Get the Message Identifier of the Subject message */
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++) {
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("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,
(int)length, 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 RecipGetIntParam: %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 RecipGetIntParam: %s\n",
X400msError(status));
}
printf("Non-Delivery Diagnostic: %d\n", intparam);
}
}
status = X400msMsgDelete(mp, 0);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from X400msMsgDelete: %s\n",
X400msError(status));
}
return status;
}
static int handle_ipn(
struct X400msMessage *mp
)
{
struct X400Recipient *rp;
int status;
char buffer[BUFSIZ];
size_t length;
int intparam;
/* The X400_S_OR_ADDRESS in the message is the IPN originator */
/* not clear why X400_ORIGINATOR doesn;t work */
status = X400msMsgGetStrParam(mp, X400_S_OR_ADDRESS,
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from MsgGetStrParam (X400_S_OR_ADDRESS): %s\n",
X400msError(status));
} else {
printf("IPN Originator: %.*s\n", (int)length, buffer);
}
/* Obtain the envelope recipient address */
if ( status != X400_E_NOERROR ) {
fprintf(stderr, "Error from X400msRecipGet (X400_RECIP_ENVELOPE): %s\n",
X400msError(status));
} else {
buffer, sizeof buffer, &length);
if ( status != X400_E_NOERROR ) {
fprintf(stderr, "Error from X400RecipGetStrParam (X400_S_OR_ADDRESS): %s\n",
X400msError(status));
} else {
buffer[length] = '\0';
printf("IPN Recipient: %.*s\n", (int)length, buffer);
}
}
/* The subject message identifier */
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from MsgGetStrParam (X400_S_SUBJECT_IPM): %s\n",
X400msError(status));
} else {
printf("Subject Message Identifier: %.*s\n", (int)length, buffer);
}
/* The conversion EITs */
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from MsgGetStrParam (X400_S_CONVERSION_EITS): %s\n", X400msError(status));
} else {
printf("conversion EITs: %.*s\n", (int)length, buffer);
}
/* non-receipt reason */
&intparam);
if (status == X400_E_NOERROR) {
printf(" non-receipt reason: %d\n", intparam);
} else {
fprintf(stderr, "Error getting non-receipt reason: %s\n",
X400msError(status));
}
/* discard reason */
&intparam);
if (status == X400_E_NOERROR) {
printf("discard reason: %d\n", intparam);
} else {
fprintf(stderr, "Error getting discard reason: %s\n",
X400msError(status));
}
/* Autoforward comment */
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from MsgGetStrParam (X400_S_AUTOFORWARD_COMMENT): %s\n",
X400msError(status));
} else {
printf("autoforward comment: %.*s\n", (int)length, buffer);
}
/* Time of receipt: UTCTime format */
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from MsgGetStrParam(X400_S_RECEIPT_TIME): %s\n",
X400msError(status));
} else {
printf(" Time of receipt: (UTCTime format): %.*s\n", (int)length, buffer);
}
/* Acknowledgement mode: 0 - manual; 1 -automatic */
&intparam);
if (status == X400_E_NOERROR) {
printf(" Acknowledgement mode: (0 - manual; 1 -automatic): %d\n",
intparam);
} else {
fprintf(stderr, "Error getting Acknowledgement mode: %s\n",
X400msError(status));
}
/* Supplementary information associated with IPN */
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from MsgGetStrParam (X400_S_SUPP_RECEIPT_INFO): %s\n",
X400msError(status));
/* tidily close the session */
/* status = X400msClose(sp);
exit(status);
*/
} else {
printf(" Supplementary information: %.*s\n", (int)length, buffer);
}
if (status != X400_E_NOERROR) {
fprintf(stderr,
"Error from MsgGetIntParam (X400_N_CONTENT_TYPE,): %s\n",
X400msError(status));
} else {
printf("Content Type: %d\n", intparam);
}
return X400_E_NOERROR;
}
static int handle_msg(
struct X400msSession *sp,
struct X400msMessage *mp
)
{
int status;
int intparam;
size_t length;
char buffer[BUFSIZ];
struct X400Recipient *rp;
int n;
/* Size */
status =
&intparam);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from MsgGetIntParam: %s\n",
X400msError(status));
}
printf("Size of Message: %d\n", intparam);
/* content type */
status = X400msMsgGetIntParam(mp, X400_N_CONTENT_TYPE, &intparam);
if (status != X400_E_NOERROR) {
fprintf(stderr,
"Error from MsgGetIntParam (X400_N_CONTENT_TYPE,): %s\n",
X400msError(status));
} else {
printf("Content Type: %d\n", intparam);
}
/* The external content type */
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from MsgGetStrParam (X400_S_EXTERNAL_CONTENT_TYPE): %s\n",
X400msError(status));
} else {
printf("External Content Type: %.*s\n", (int)length, buffer);
}
/* 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);
/* display any PCT info available */
get_4406_info(mp);
/* The ORADDRESS in the message is the (envelope) originator */
status = X400msMsgGetStrParam(mp, X400_S_OR_ADDRESS,
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 envelope recipients */
for (n = 1;; n++) {
status = X400msRecipGet(mp, X400_RECIP_ENVELOPE, n, &rp);
if (status == X400_E_NO_RECIP)
break;
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from RecipGet (envelope): %s\n",
X400msError(status));
/* tidily close the session */
status = X400msClose(sp);
exit(status);
}
/* Note: recipient may not actually have an O/R address */
status = X400msRecipGetStrParam(rp, X400_S_OR_ADDRESS,
buffer, sizeof buffer, &length);
if (status == X400_E_NOERROR) {
printf("Env Recipient %d: %.*s\n", n, (int)length, buffer);
}
/* get back status of the Proof Of Del Request in the recipient */
&intparam);
if (status == X400_E_NOERROR) {
printf("Recipient proof of delivery request is %d\n", intparam);
} else {
fprintf(stderr, "Error getting proof of delivery request: %s\n",
X400msError(status));
}
/* report content integrity check info if available */
get_cic(rp);
/* return MessageToken info if available */
report_msg_token_info(rp);
/* get and display the seccurity label if available */
get_sec_label(mp);
}
/* Get the primary recipients */
for (n = 1;; n++) {
if (status == X400_E_NO_RECIP)
break;
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from RecipGet (primary): %s\n", X400msError(status));
/* This is allowed, so continue reading the message */
break;
}
/* Note: recipient may not actually have an O/R address */
status = X400msRecipGetStrParam(rp, X400_S_OR_ADDRESS,
buffer, sizeof buffer, &length);
if (status == X400_E_NOERROR) {
printf("Primary Recipient %d: %.*s\n", n, (int)length, buffer);
}
if (status == X400_E_NOERROR) {
printf("Primary Recipient Precedence %d\n", intparam);
} else {
fprintf(stderr, "Error getting Primary Recipient Precedence : %s\n", X400msError(status));
}
}
/* 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);
else
printf("No IA5 Text content (%d: %s)\n", status, X400msError(status));
/* get all the attachments */
printf("Getting body parts\n");
get_body_parts(mp);
return X400_E_NOERROR;
}
static int send_ipn(
struct X400msSession *sp,
struct X400msMessage *mp,
struct X400msMessage **ipn
)
{
int status;
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msMsgNew returned error: %s\n",
X400msError (status));
return (status);
}
status = X400msMakeIPN(mp, -1, ipn);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from X400msMakeIPN: %s\n",
X400msError(status));
return status;
}
/* submit */
status = X400msMsgSend (*ipn);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "x400msMsgSend returned error: %s\n",
X400msError (status));
return (status);
} else {
printf("IPN submitted successfully\n");
}
return status;
}
/*
* 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 *local_trusted_ca_certs_dir
)
{
int status;
/* Directory containing trusted CA Certificates */
printf(" Adding %s as trusted CA cert dir\n", trusted_ca_certs_dir);
local_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;
}
static void report_msg_token_info(
struct X400Recipient *rp
)
{
char buffer[BUFSIZ];
int status;
int param;
size_t length;
status = X400msRecipGetIntParam(rp,
X400_N_MSGTOK_STATUS, ¶m);
fprintf(stderr, "No MessageToken present in recipient\n");
/* no further information available */
return ;
fprintf(stderr, "Error from RecipGetIntParam: %s (%d)\n",
X400msError(status),
fprintf(stderr, "Message Token status not available\n");
} else {
fprintf(stderr,
"Message Token status %d \n", param);
}
switch (param) {
case X400_E_NOERROR:
fprintf(stderr, "Token OK (%d)\n", param);
break;
fprintf(stderr,
"Message Token validation cannot take place because the security environment is invalid (%d):\n",
param);
/* other values will not be available */
return ;
fprintf(stderr,
"Message Token validation failed (%d): %s\n",
param, X400msError(param));
break;
default:
fprintf(stderr,
"Unexpected Message Token validation result (%d): %s\n",
param, X400msError(param));
break;
}
//show_certificate (rp, X400_N_CERT_MSGTOK, "message-token");
status = X400msRecipGetStrParam(rp,
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from RecipGetStrParam: %s\n",
X400msError(status));
fprintf(stderr, "recipient in token not available\n");
} else {
fprintf(stderr,
"Message Token(%u): recipient in Token '%.*s'\n",
(unsigned)length, (int)length, buffer);
}
status = X400msRecipGetStrParam(rp,
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
X400msError(status),
fprintf(stderr, "Message Token DER not available\n");
} else {
fprintf(stderr,
"Message Token DER available (%u bytes)\n", (unsigned)length);
}
status = X400msRecipGetIntParam(rp,
X400_N_MSGTOK_SEQ_NUM, ¶m);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
X400msError(status),
fprintf(stderr, "Message Token seq num not available\n");
} else {
fprintf(stderr,
"Message Token seq num %d \n", param);
}
status = X400msRecipGetStrParam(rp,
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
X400msError(status),
fprintf(stderr, "Message Token Security Label DER not available\n");
} else {
fprintf(stderr,
"Message Token Security Label DER available (%u bytes)\n", (unsigned)length);
fprintf(stderr, "Security Label from Message Token is:\n");
print_sec_label((unsigned char *)buffer, length);
}
/* get back status of the Content Integrity Check in the message token */
¶m);
if (status == X400_E_NO_VALUE) {
printf("No Content Integrity Check in token\n");
printf("Error from RecipGetIntParam: %s\n", X400msError(status));
} else {
/* report CIC information */
switch (param) {
case X400_E_NOERROR:
printf("Content Integrity Check in token succeeded\n");
break;
default:
printf("Content Integrity Check in token error (%d): %s\n",
param, X400msError(param));
break;
}
status = X400msRecipGetStrParam(rp,
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
X400msError(status),
fprintf(stderr, "Message Token Content Integrity Check DER not available\n");
} else {
fprintf(stderr,
"Message Token Content Integrity Check DER available (%u bytes)\n",
(unsigned)length);
}
//show_certificate (rp, X400_N_CERT_MSGTOK_CIC, "token CIC");
}
status = X400msRecipGetIntParam(rp,
X400_N_MSGTOK_PODR_STATUS, ¶m);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
X400msError(status),
fprintf(stderr, "Message Token proof of delivery status not available\n");
} else {
fprintf(stderr,
"Message Token proof of delivery status %d \n", param);
}
status = X400msRecipGetIntParam(rp,
X400_N_MSGTOK_SEC_LAB_STATUS, ¶m);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
X400msError(status),
fprintf(stderr, "Message Token security label status not available\n");
} else {
fprintf(stderr,
"Message Token security label status %d \n", param);
}
status = X400msRecipGetIntParam(rp,
X400_N_MSGTOK_RECIP_STATUS, ¶m);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from RecipGetStrParam: %s (%d)\n",
X400msError(status),
fprintf(stderr, "Message Token recip status not available\n");
} else {
fprintf(stderr,
"Message Token recip status %d \n", param);
}
return;
}
static int get_sec_label(
struct X400msMessage *mp
)
{
unsigned char slab_buffer[XML_BUFSIZE];
int status;
size_t length;
status = X400msMsgGetStrParam(mp,
(char*)slab_buffer,
XML_BUFSIZE,
&length);
if (status == X400_E_NO_VALUE) {
printf("No security label\n");
fprintf(stderr,"Failed to fetch security label: %d",status);
return (status);
} else {
fprintf(stderr, "Security Label from envelope is:\n");
print_sec_label(slab_buffer, length);
}
return X400_E_NOERROR;
}
static void print_sec_label(
unsigned 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(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 int get_cic(
struct X400Recipient *rp
)
{
char buffer[BUFSIZ];
int status, cic_status;
int intparam;
size_t length;
/* get back status of the Content Integrity Check in the recipient */
&intparam);
if (cic_status == X400_E_NO_VALUE) {
printf("No Content Integrity Check in recipient\n");
return X400_E_NOERROR;
printf("Error from RecipGetIntParam: %s\n", X400msError(cic_status));
return cic_status;
}
/* report CIC information */
switch (intparam) {
case X400_E_NOERROR:
printf("Content Integrity Check succeeded\n");
break;
default:
printf("Content Integrity Check error (%d): %s\n",
intparam, X400msError(intparam));
break;
}
/* Return the Content Integrity Check */
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error getting recipient cic: %s\n",
X400msError(status));
} else {
printf("Content Integrity Check found in recipient (%d)\n",
(int)length);
}
//show_certificate (rp, X400_N_CERT_RECIP_CIC, "recipient CIC");
return X400_E_NOERROR;
}
static int get_4406_info(
struct X400msMessage *mp
)
{
int status;
int intparam;
size_t length;
char buffer[BUFSIZ];
/* get the 4406 status which tells us if it's PCT or not */
if (status == X400_E_NO_VALUE ) {
printf("4406 Status (X400_N_S4406_STATUS) absent so not PCT: %s\n", X400msError(status));
return X400_E_NOERROR;
}
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from MsgGetIntParam (X400_N_S4406_STATUS): %s\n",
X400msError(status));
} else {
printf("4406 Status(X400_N_S4406_STATUS): %d\n", intparam);
}
/* get the 4406 security elements */
if (status == X400_E_NO_VALUE ) {
printf("4406 absent: %s\n", X400msError(status));
}
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from MsgGetIntParam (X400_N_S4406): %s\n",
X400msError(status));
} else {
printf("4406 (X400_N_S4406): %d\n", intparam);
}
/* Get the Message Identifier of the Subject message */
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error from MsgGetStrParam (X400_S_S4406_STATUS_DETAIL): %s\n",
X400msError(status));
return (status);
}
printf("S4406 Status Detail (X400_S_S4406_STATUS_DETAIL): %.*s\n", (int)length, buffer);
show_message_certificate (mp, "S4406");
return X400_E_NOERROR;
}
static void show_message_certificate (
struct X400msMessage *mp,
const char *tag ARGNOTUSED)
{
int status;
struct X400Certificate *cert;
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "Error getting S4406 certificate: %s\n",
X400msError (status));
return;
}
show_certificate(cert, "X400_N_S4406_CERTIFICATE");
return;
}
static void show_recip_certificate (
struct X400Recipient *rp,
int certtype,
const char *tag)
{
int status;
struct X400Certificate *cert;
status = X400RecipGetCert (rp, certtype, &cert);
if ( status != X400_E_NOERROR ) {
fprintf (stderr, "Error getting %s certificate: %s\n",
tag, X400msError (status));
return;
}
show_certificate(cert, tag);
return;
}
static void show_certificate (
struct X400Certificate *cert,
const char *tag)
{
int status;
char buffer[BUFSIZ];
size_t length;
int paramval;
/* Return the subject DN from Orig cert */
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error getting subject of cert used for %s: %s\n",
tag, X400msError(status));
} else {
printf("Subject of Cert used to verify %s (%.*s)\n",
tag, (int)length, buffer);
}
/* Return the issuer DN from Orig cert */
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error getting issuer of cert used for %s: %s\n",
tag, X400msError(status));
} else {
printf("Issuer of Cert used to verify %s (%.*s)\n",
tag, (int)length, buffer);
}
/* Return the serial number from Orig cert used to verify the
* Content Integrity Check */
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error getting serial num of cert used for %s: %s\n",
tag, X400msError(status));
} else {
printf("Serial Num of Cert used to verify %s (%.*s)\n",
tag, (int)length, buffer);
}
/* Return the Orig cert used to verify the Content Integrity Check */
buffer, sizeof buffer, &length);
if (status != X400_E_NOERROR) {
fprintf(stderr, "Error getting cert der used for %s: %s\n",
tag, X400msError(status));
} else {
printf(
"Returned Cert used to verify %s (%d)\n",
tag, (int)length);
}
/* Find any ORaddress subject alt name and its status */
status = X400CertGetStrParam(cert, X400_S_OR_ADDRESS,
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 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 -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 -E : Fetch messages until all read\n");
printf("\t -Y : Filename of PKCS12 file containing Digital Identity\n");
printf("\t -U : Directory containing trust anchors\n");
printf("\t -I : Generate IPN from message received\n");
return;
}
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 ...
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.
int X400RecipGetStrParam(struct X400Recipient *rp, int paramtype, char *buffer, size_t buflen, size_t *paramlenp)
Return a string-valued parameter from the recipient object.
int X400msSetStrDefault(struct X400msSession *sp, int paramtype, const char *value, size_t length)
Set a default string parameter value in a session.
int X400CertGetIntParam(struct X400Certificate *cp, int paramtype, int *valp)
Return a integer-valued parameter from the certificate object.
int X400msMsgGetCert(struct X400msMessage *mp, int certtype, struct X400Certificate **certp)
Get certificate object from message This returns a certificate which was used to sign an object in th...
#define X400_E_X509_VERIFY_FAIL_NO_PUBKEY
Definition: x400_att.h:187
int X400msRecipGetIntParam(struct X400Recipient *rp, int paramtype, int *valp)
Return a integer-valued parameter from the recipient object.
int X400msMsgGet(struct X400msSession *sp, int number, struct X400msMessage **mpp, int *typep, int *seqp)
Get message object for transfer out from MS or MTA via P3.
const char * X400msError(int error)
Obtain a string describing the meaning of the given error code.
int X400msMsgNew(struct X400msSession *sp, int type, struct X400msMessage **mpp)
Creates new message.
int X400msWait(struct X400msSession *sp, int seconds, int *count)
Wait for messages to be ready to be read.
int X400msRecipGet(struct X400msMessage *mp, int type, int number, struct X400Recipient **rpp)
Get recipient object from message.
int X400msRecipGetStrParam(struct X400Recipient *rp, int paramtype, char *buffer, size_t buflen, size_t *paramlenp)
Return a string-valued parameter from the recipient object.
X400 MA/MS (P3/P7) Interface.
#define X400_E_X509_VERIFY_FAIL_UNSUPPORTED_ALG
Definition: x400_att.h:193
int X400msMsgGetIntParam(struct X400msMessage *mp, int paramtype, int *valp)
Return a integer-valued parameter from the message object.
#define X400_E_X509_VERIFY_FAIL_INCOMPAT_ALG
Definition: x400_att.h:190
int X400msSetIntDefault(struct X400msSession *sp, int paramtype, int value)
Set a default integer parameter value in a session.
#define X400_B_RETURN_VERIFICATION_ERRORS
Definition: x400_att.h:1099
int X400msMsgGetStrParam(struct X400msMessage *mp, int paramtype, char *buffer, size_t buflen, size_t *paramlenp)
Return a string-valued parameter from the message object.
int X400CertGetStrParam(struct X400Certificate *cp, int paramtype, char *buffer, size_t buflen, size_t *paramlenp)
Return a string-valued parameter from the certificate object.
int X400msMakeIPN(struct X400msMessage *mp, int non_receipt_reason, struct X400msMessage **mpp)
Make an IPN based on the subject IPM.