How to get linked beans function in SuiteCRM - suitecrm

I want to setup email notification in suitecrm. I have created the logic hook and email notification php file. However my issue is that when it reaches this line $GLOBALS['log']->fatal("Could not find the department NC was issued to: ". $bean->name); it throws the error message. But I'm not understanding as to why it throws the error message if me syntax is incorrect.
class nc_email_notification {
public function email_notification(&$bean, $events, $arguments){
/*define 'review_pending' as string constant */
/*Get sugar email engine*/
$email = new SugarPHPMailer();
$email->From = 'suitecrm#gmail.com';
$email->FromName ='SuiteCRM';
/*Get the Department NC was Issued to */
$dept_array= $bean->get_linked_beans('dept_department_nccas_nc_case','dept_Department_sugar');
if(count($dept_array)==0){
/*log error*/
$GLOBALS['log']->fatal("Could not find the department NC was issued to: ". $bean->name);
}else{
/* Get email of users within the Department NC is issued to */
$user_array = $dept_array[0]->get_linked_beans('dept_department_users','User');
if(count($user_array)==0){
/*log error*/
$GLOBALS['log']->fatal("Could not find Users within the department NC is issued to: ". $bean->name);
}else{
$address=getDepartmentUsersEmail($user_array);
}
/*Get the Department NC was raised by */
$raised_dept_array= $bean->get_linked_beans('dept_department_nccas_nc_case_1','dept_Department_sugar');
if(count($raised_dept_array)==0){
/*log error*/
$GLOBALS['log']->fatal("Could not find the department NC was raised by: ". $bean->name);
}else {
/*Get email of users within the Department NC is raised by*/
$raised_user_array = $raised_dept_array[0]->get_linked_beans('dept_department_users','User');
if(count($raised_user_array)==0){
/*log error*/
$GLOBALS['log']->fatal("Could not find Users within the department NC is raised by: ". $bean->name);
}
else {
$r_user_address = getDepartmentUsersEmail($raised_user_array);
}
}
/*Get the Quality Systems Department*/
//$qual_dept=$dept_array[0]->retrieve)by)string_fields(array('name' => 'Quality Systems' ));
//$qual_dept->load_relationship('dept_department_email_addresses_primary');
/* Send email to Manager */
$rev_email = 'ramon#gmail.com';
/*Get NC Action for the NC Case*/
$action_array = $bean->get_linked_beans('nccas_nc_case_ncact_nc_action','ncact_NC_Action_sugar');
/* Get sugar template engine */
$xtpl = new XTemplate("XTemplate/NCEmailTemplate.html");
/*GEt the URL for the NC Case */
$url = $GLOBALS['sugar_config']['site_url'].'index.php?module=ncase_NonConformance&action=DetailView&record='.$bean->id;
$xtpl -> assign('URL', $url);
/* Get NC Status */
$nc_status=trim($bean->getFieldValue('status'));
/* Get NC ID */
$id = $bean->getFieldValue('id');
if(empty($bean->fetched_row['id'])){
$email=createNCEmail($email,$rev_email,'New NC Email Notification',$bean,$xtpl);
/* Send email to Quality System Manager */
$email->addaddress($rev_email);
/* Send email to users of Issued to department */
foreach($address as $uemail){
$email->addAddress($uemail);
}
}else {
if (strcasecmp ($nc_status,'review_pending')==0){
/* Set Email Subject */
$email->Subject = 'NC Case: '. ''. $bean->name . ' '. ' is pending review';
/* Send email to users of Raised by department */
foreach($r_user_address as $uemail){
$email->addAddress($uemail);
}
/* Send email to Quality System Manager */
$email->addaddress($rev_email);
/* Create email message using email template */
$email=createNCEmailwithAction($email,$action_array,$bean,$xtpl);
} else if (strcasecmp ($nc_status,'Closed')==0){
/* Set Email Subject */
$email->Subject = 'NC Case: '. ''. $bean->name . ''. ' is Closed';
/* Send email to users of Raised by department */
foreach($r_user_address as $uemail){
$email->addAddress($uemail);
}
/* Send email to Issued to Department */
foreach($address as $iemail){
$email->addAddress($iemail);
}
/* Create email message using email template*/
$email=createNCEmailwithAction($email,$action_array,$bean,$xtpl);
} else{
If ($bean->fetched_row['description'] != $bean->description){
/* Set Email Subject */
$email->Subject = 'NC Case: ' .''. $bean->name .''. ' has been modified';
/* Create email message using email template */
$email=createNCEmailwithAction($email,$action_array,$bean,$xtpl);
/* Build appropriate email list */
foreach($address as $uemail){
$email->addAddress($uemail);
}
/* Send email to Quality System Manager */
$email->addaddress($rev_email);
}
}
}
Logic Hook
$hook_version = 1;
$hook_array = Array();
$hook_array['before_save'] = Array();
$hook_array['before_save'][] = Array(1, 'Create NC email object', 'custom/Extension/modules/ncase_NonConformance/Ext/email_notification.php','nc_email_notification', 'email_notification');

Unfortunately I know nothing about the name of your fields.
First check the 'dept_department_nccas_nc_case'(should be $field_name) and 'dept_Department_sugar'(should be $bean_name).
Also you can try to use load_relationship

Related

My C with MQ receive a message return code 2037

I run the C program, which connect to MQ and try to get a message from it. I always get a message:
MQGET ended with reason code 2037
which means that MQ is not opened, but MQOPEN CC=0 RC=0
MQ error log is empty.
this is the program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cmqc.h> /* includes for MQI*/
#include <cmqxc.h>
int main(int argc, char **argv)
{
MQCNO Connect_options = {MQCNO_DEFAULT};/MQNONNX opt*/
MQCD ClientConn = {MQCD_CLIENT_CONN_DEFAULT};/*client channel*/
MQHCONN Hcon; /* connection handle */
MQHOBJ Hobj; /* object handle */
MQLONG CompCode; /* completion code */
MQLONG OpenCode; /* MQOPEN completion code*/
MQLONG Reason; /* reason code */
MQOD od = {MQOD_DEFAULT}; /* Object Descriptor */
MQMD md = {MQMD_DEFAULT}; /* Message Descriptor */
MQPMO pmo = {MQPMO_DEFAULT}; /* put message options*/
MQLONG O_options; /* MQOPEN options */
MQLONG C_options; /* MQCLOSE options */
MQGMO gmo = {MQGMO_DEFAULT}; /* get message options */
char QMgrName[MQ_Q_MGR_NAME_LENGTH+1];
char QName[MQ_Q_NAME_LENGTH+1];
char channelName[MQ_CHANNEL_NAME_LENGTH+1];
char hostname[1024];
char port[4];
MQLONG buflen; /* buffer length*/
char TempBuf[65536];
int msgsToGet;
int msgsGot;
if (argc != 6)
{
printf("Usage: MQTest11 QMgrName ChlName hostname port QName\n");
return(1);
}
**/* copy MQ manager name */**
strncpy(QMgrName, argv[1], MQ_Q_MGR_NAME_LENGTH);
QMgrName[MQ_Q_MGR_NAME_LENGTH] = '\0';
**/* copy channel name */**
strncpy(channelName, argv[2], MQ_CHANNEL_NAME_LENGTH);
channelName[MQ_CHANNEL_NAME_LENGTH] = '\0';
**/* copy hostname */**
strncpy(hostname, argv[3], 1023);
hostname[1023] = '\0';
**/* copy port number */**
strncpy(port,argv[4],4);
strncpy(QName, argv[5], MQ_Q_NAME_LENGTH);
QName[MQ_Q_NAME_LENGTH] = '\0';
**/* copy hostname for connection */**
strncpy(ClientConn.ConnectionName,hostname, MQ_CONN_NAME_LENGTH);
**/* copy channel name */**
strncpy(ClientConn.ChannelName,channelName,MQ_CHANNEL_NAME_LENGTH);
**/* Point the MQCNO to the client connection definition */**
Connect_options.ClientConnPtr = &ClientConn;
Connect_options.Version = MQCNO_VERSION_2;
**/* use MQCONNX */**
if (CompCode == MQCC_FAILED)
{
/* exit with print the reason */
}
else
{
strncpy(od.ObjectName, QName, (size_t)MQ_Q_NAME_LENGTH);
O_options = MQOO_OUTPUT + MQOO_FAIL_IF_QUIESCING;
MQOPEN(Hcon, /* connection handle */
&od, /* object descriptor for queue */
O_options, /* open options */
&Hobj, /* object handle */
&OpenCode, /* MQOPEN completion code */
&Reason); /* reason code */
printf("MQTest11 MQOPEN CC=%ld RC=%ld\n", CompCode, Reason);
if (OpenCode == MQCC_OK) /* if MQOPEN , then continue in the while loop */
{
gmo.Options = MQGMO_WAIT + MQGMO_CONVERT;
gmo.WaitInterval = 15000;
msgsGot = 0;
msgsToGet = 0;
CompCode = OpenCode;
}
while (CompCode != MQCC_FAILED && ((msgsToGet == 0) || (msgsGot < msgsToGet)))
{
/* define length of the buffer -1 */
buflen = strlen(TempBuf) - 1; */ buffer length */
memcpy(md.MsgId, MQMI_NONE, sizeof(md.MsgId)); /*copy msg ID*/
memcpy(md.CorrelId, MQCI_NONE, sizeof(md.CorrelId));/*copy corrlID*/
md.Encoding = MQENC_NATIVE; /*encode*/
md.CodedCharSetId = MQCCSI_Q_MGR;
/* function to get message from MQ*/
MQGET(Hcon, /* get message from MQ */
Hobj, /* object handle*/
&md, /* message descriptor*/
&gmo, /*get message options*/
buflen, /*buffer length*/
TempBuf, /* buffer */
&messlen, /* message length*/
&CompCode, /* completion code*/
&Reason); /* reason code*/
**/* I put some statements to check if transaction failed or not*/**
if (Reason != MQRC_NONE)
{
if (Reason == MQRC_NO_MSG_AVAILABLE)
{
/* print statement no more messages */
else
{
printf("MQGET ended with reason code %d comcode %d\n",Reason,CompCode);
if (Reason == MQRC_TRUNCATED_MSG_FAILED)
{
/print statement that it is failed*/
}
}
}
**This is almost done, only statement if Compcode not failed, then print buffer**
I have changed char TempBuf declaration to MQBYTE and it is not help
MQRC 2037 is MQRC_NOT_OPEN_FOR_INPUT, you can find this information by running the mqrc command provided with the IBM MQ Client or server install, below is a sample output on a Linux server:
$ mqrc 2037
2037 0x000007f5 MQRC_NOT_OPEN_FOR_INPUT
You do not show the MQOPEN call but if it is using the O_options, it would be explained by this, you currently have the following:
O_options = MQOO_OUTPUT + MQOO_FAIL_IF_QUIESCING;
This should someing like the following:
O_options = MQOO_INPUT_AS_Q_DEF + MQOO_FAIL_IF_QUIESCING;
I would suggested that you review the sample applications provided with the IBM MQ install. On Linux these would be located in /opt/mqm/samp. The sample amqsget0.c would be similar to your program except it is using a MQCONN not MQCONNX.

Linphone registration and placing call using C API (Windows)

Could you please help me with next question.
I'm trying to make registration and place call with Linphone thru C API (Windows).
I can separately successfully register with local SIP server using this tutorial
Basic registration , but I don't know how to place a call after registration using this tutorial Basic call.
The problem is that Basic registration code contains eternal loop executing while application is running:
while (running){
linphone_core_iterate(lc); /* first iterate initiates registration */
ms_usleep(50000);
}
and Basic call code also contains eternal loop executing while application is running:
while(running){
linphone_core_iterate(lc);
ms_usleep(50000);
}
If to place Basic call code into first loop, program will try to place call again and again. How to make registration, and then place a call? Could you help me with that? Thanks.
My unworking code:
#ifdef IN_LINPHONE
#include "linphonecore.h"
#else
#include "linphone/linphonecore.h"
#endif
#include <signal.h>
static bool_t running = TRUE;
static void stop(int signum){
running = FALSE;
}
/*
* Call state notification callback
*/
static void call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg){
switch (cstate){
case LinphoneCallOutgoingRinging:
printf("It is now ringing remotely !\n");
break;
case LinphoneCallOutgoingEarlyMedia:
printf("Receiving some early media\n");
break;
case LinphoneCallConnected:
printf("We are connected !\n");
break;
case LinphoneCallStreamsRunning:
printf("Media streams established !\n");
break;
case LinphoneCallEnd:
printf("Call is terminated.\n");
break;
case LinphoneCallError:
printf("Call failure !");
break;
default:
printf("Unhandled notification %i\n", cstate);
}
}
static void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message){
printf("New registration state %s for user id [%s] at proxy [%s]\n"
, linphone_registration_state_to_string(cstate)
, linphone_proxy_config_get_identity(cfg)
, linphone_proxy_config_get_addr(cfg));
}
LinphoneCore *lc;
int main(int argc, char *argv[]){
LinphoneCoreVTable vtable = { 0 };
LinphoneCore *lc;
LinphoneCall *call = NULL;
const char *dest = "sip:sip2#officesip.local";
LinphoneProxyConfig* proxy_cfg;
LinphoneAddress *from;
LinphoneAuthInfo *info;
char* identity = "sip:sip#officesip.local";
char* password = "sip";
const char* server_addr;
/* takes sip uri identity from the command line arguments */
/*if (argc>1){
identity = argv[1];
}
/* takes password from the command line arguments */
/*if (argc>2){
password = argv[2];
}
*/
//signal(SIGINT, stop);
#ifdef DEBUG
linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/
#endif
/*
Fill the LinphoneCoreVTable with application callbacks.
All are optional. Here we only use the registration_state_changed callbacks
in order to get notifications about the progress of the registration.
*/
vtable.registration_state_changed = registration_state_changed;
vtable.call_state_changed = call_state_changed;
/*
Instanciate a LinphoneCore object given the LinphoneCoreVTable
*/
lc = linphone_core_new(&vtable, NULL, NULL, NULL);
/*create proxy config*/
proxy_cfg = linphone_proxy_config_new();
/*parse identity*/
from = linphone_address_new(identity);
if (from == NULL){
printf("%s not a valid sip uri, must be like sip:toto#sip.linphone.org \n", identity);
goto end;
}
if (password != NULL){
info = linphone_auth_info_new(linphone_address_get_username(from), NULL, password, NULL, NULL, NULL); /*create authentication structure from identity*/
linphone_core_add_auth_info(lc, info); /*add authentication info to LinphoneCore*/
}
// configure proxy entries
linphone_proxy_config_set_identity(proxy_cfg, identity); /*set identity with user name and domain*/
server_addr = linphone_address_get_domain(from); /*extract domain address from identity*/
//linphone_proxy_config_set_server_addr(proxy_cfg, server_addr); /* we assume domain = proxy server address*/
linphone_proxy_config_set_server_addr(proxy_cfg, "localhost");
linphone_proxy_config_enable_register(proxy_cfg, TRUE); /*activate registration for this proxy config*/
linphone_address_destroy(from); /*release resource*/
linphone_core_add_proxy_config(lc, proxy_cfg); /*add proxy config to linphone core*/
linphone_core_set_default_proxy(lc, proxy_cfg); /*set to default proxy*/
/* main loop for receiving notifications and doing background linphonecore work: */
while (running){
linphone_core_iterate(lc); /* first iterate initiates registration */
ms_usleep(50000);
//------------------------------------------------------------------------------------------------------
//HERE I'M TRYING TO PLACE A CALL INSIDE LOOP
//------------------------------------------------------------------------------------------------------
if (dest){
/*
Place an outgoing call
*/
call = linphone_core_invite(lc, dest);
if (call == NULL){
printf("Could not place call to %s\n", dest);
goto end;
}
else printf("Call to %s is in progress...", dest);
linphone_call_ref(call);
}
//------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
}
linphone_core_get_default_proxy(lc, &proxy_cfg); /* get default proxy config*/
linphone_proxy_config_edit(proxy_cfg); /*start editing proxy configuration*/
linphone_proxy_config_enable_register(proxy_cfg, FALSE); /*de-activate registration for this proxy config*/
linphone_proxy_config_done(proxy_cfg); /*initiate REGISTER with expire = 0*/
while (linphone_proxy_config_get_state(proxy_cfg) != LinphoneRegistrationCleared){
linphone_core_iterate(lc); /*to make sure we receive call backs before shutting down*/
ms_usleep(50000);
}
end:
printf("Shutting down...\n");
linphone_core_destroy(lc);
printf("Exited\n");
return 0;
}
Here is the solution from this example, use:
/* Loop until registration is OK */
do {
linphone_core_iterate(lc); /* first iterate initiates registration */
ms_usleep(100000);
} while (running && linphone_proxy_config_get_state(proxy_cfg) == LinphoneRegistrationProgress);
instead of:
while (running){
linphone_core_iterate(lc); /* first iterate initiates registration */
ms_usleep(50000);
}
After that I can call and send\receive text messages.

Ldap Search on the host server

I developed a small C++ application to bind a user in a server using active directory then return the name of his group.
The probleme is when I run the application from a remote computer, it run with no probleme. When I try to run it at the host server, -the computer hosting the active directory- the binding process pass, but the searching function always return Operation error: this is a sample of my code.
if ((rc = ldap_simple_bind_s( ld, loginDN, password )) != LDAP_SUCCESS )
{
printf("ldap_simple_bind_s: %s\n", ldap_err2string( rc ));
ldap_unbind_s( ld );
return 10;
}
printf("Bind and authentication to the server successful\n");
string a="(&(objectclass=person)(cn="+prenom+" "+nom+"))";
rc = ldap_search_ext_s(
ld, /* LDAP session handle */
searchBase, /* container to search */
LDAP_SCOPE_ONELEVEL, /* search scope */
a.c_str(), /*search filter*/
NULL, /* return all attributes */
0, /* return attributes and values */
NULL, /* server controls */
NULL, /* client controls */
&timeOut, /* search timeout */
LDAP_NO_LIMIT, /* no size limit */
&searchResult ); /* returned results */
if ( rc != LDAP_SUCCESS )
{
cout<<rc<<endl;
printf("ldap_search_ext_s: %s\n", ldap_err2string( rc ));
ldap_msgfree( searchResult );
ldap_unbind_s( ld );
return 20 ;
}
I found the answer I must use the port 3268 instead of 389

TLS START ERROR IN LIBSTROPHE

I want to create a simple chat client using libstrophe library. The code i have written is as below.
The connection with the gmail server is made. But I am getting a TLS error , which i cannot solve.
Please suugest what is causing the error.
#include <stdio.h>
#include <string.h>
#include <strophe.h>
int handle_reply(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza,void * const userdata)
{
xmpp_stanza_t *query, *item;
char *type;
type = xmpp_stanza_get_type(stanza);
if (strcmp(type, "error") == 0)
fprintf(stderr, "ERROR: query failed\n");
else {
query = xmpp_stanza_get_child_by_name(stanza, "query");
printf("Active Sessions:\n");
for (item = xmpp_stanza_get_children(query); item;
item = xmpp_stanza_get_next(item))
printf("\t %s\n", xmpp_stanza_get_attribute(item, "jid"));
printf("END OF LIST\n");
}
/* disconnect */
xmpp_disconnect(conn);
return 0;
}
/* define a handler for connection events */
void conn_handler(xmpp_conn_t * const conn, const xmpp_conn_event_t status,
const int error, xmpp_stream_error_t * const stream_error,
void * const userdata)
{
xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
xmpp_stanza_t *iq, *query;
if (status == XMPP_CONN_CONNECT)
{
fprintf(stderr, "DEBUG: connected\n");
/* create iq stanza for request */
iq = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(iq, "iq");
xmpp_stanza_set_type(iq, "get");
xmpp_stanza_set_id(iq, "active1");
xmpp_stanza_set_attribute(iq, "to", "xxxxxxxxx.com");
query = xmpp_stanza_new(ctx);
xmpp_stanza_set_name(query, "query");
xmpp_stanza_set_ns(query, XMPP_NS_DISCO_ITEMS);
xmpp_stanza_set_attribute(query, "node", "sessions");
xmpp_stanza_add_child(iq, query);
/* we can release the stanza since it belongs to iq now */
xmpp_stanza_release(query);
/* set up reply handler */
xmpp_id_handler_add(conn, handle_reply, "active1", ctx);
/* send out the stanza */
xmpp_send(conn, iq);
/* release the stanza */
xmpp_stanza_release(iq);
}
else {
fprintf(stderr, "DEBUG: disconnected\n");
xmpp_stop(ctx);
}
}
int main(int argc, char **argv)
{
int a;
xmpp_ctx_t *ctx;
xmpp_conn_t *conn;
xmpp_log_t *log;
char *jid, *pass, *host;
jid = "ACCOUNTNAME#gmail.com";
pass = "MYPASSWORD";
host = NULL;
/* init library */
xmpp_initialize();
/* create a context */
log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG); /* pass NULL instead to silence output */
ctx = xmpp_ctx_new(NULL, log);
/* create a connection */
conn = xmpp_conn_new(ctx);
/* setup authentication information */
xmpp_conn_set_jid(conn, jid);
xmpp_conn_set_pass(conn, pass);
/* initiate connection */
xmpp_connect_client(conn, host, 0, conn_handler, ctx);
/* enter the event loop -
our connect handler will trigger an exit */
xmpp_run(ctx);
/* release our connection and context */
xmpp_conn_release(conn);
xmpp_ctx_free(ctx);
/* final shutdown of the library */
xmpp_shutdown();
scanf("%d",&a);
return 0;
}
The cmd prompt (output) is:
xmpp DEBUG sock_connect to alt3.xmpp.l.google.com:5222 returned 304
xmpp DEBUG attempting to connect to alt3.xmpp.l.google.com
xmpp DEBUG connection successful
conn DEBUG SENT: <?xml version="1.0"?><stream:stream to="gmail.com" xml:lang="en
" version="1.0" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams">
xmpp DEBUG RECV: <stream:stream from='gmail.com' id='4EDF7B71A4D88935' version='
1.0' xmlns:stream='http://etherx.jabber.org/streams' xmlns='jabber:client'>
xmpp DEBUG RECV: <stream:features><starttls xmlns="urn:ietf:params:xml:ns:xmpp-t
ls"><required/></starttls><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><
mechanism>X-OAUTH2</mechanism><mechanism>X-GOOGLE-TOKEN</mechanism></mechanisms>
</stream:features>
TLSS DEBUG QuerySecurityPackageInfo() success
TLSS DEBUG AcquireCredentialsHandle() success
conn DEBUG SENT: <starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>, error: 0
xmpp DEBUG RECV: <proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>
xmpp DEBUG handle proceedtls called for proceed
xmpp DEBUG proceeding with TLS
**TLSS DEBUG QuerySecurityPackageInfo() success
TLSS DEBUG AcquireCredentialsHandle() success
xmpp DEBUG Couldn't start TLS! error -2146893032
conn DEBUG SENT: </stream:stream>
xmpp DEBUG parse error, disconnecting**
xmpp DEBUG Closing socket.
DEBUG: disconnected
event DEBUG Stopping event loop.
event DEBUG Event loop completed.

Verifying self-signed/expired certificate with openssl library does not return error

I am trying to write a certificate validation function in C using the openssl library. Since the certificate I am validating is self-signed and expired, I expect the X509_verify_cert() to return error (the return value is 1 and the store_ctx->error is set to X509_V_OK instead). 'openssl verify my_pem_cert_file' outputs:
error 18 at 0 depth lookup:self signed certificate
error 10 at 0 depth lookup:certificate has expired
What I am doing wrong? Here is my code:
static int cert_verify_callback(int ok, X509_STORE_CTX *ctx)
{
/* Tolerate self-signed certificate */
if (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) {
return 1;
}
/* Otherwise don't override */
return ok;
}
int cert_validate(const char* certFileName)
{
BIO *pBio = NULL;
X509 *pX509 = NULL;
X509 *CA = NULL;
X509_STORE *cert_store = NULL;
X509_STORE_CTX *store_ctx = NULL;
STACK_OF(X509) *stack_of_x509 = NULL;
time_t check_time;
int store_ctx_error;
int store_ctx_error_depth;
pBio = BIO_new( BIO_s_file_internal() );
if(pBio == NULL)
/* error handling */
if(BIO_read_filename(pBio, certFileName) <= 0)
/* error handling */
pX509 = PEM_read_bio_X509(pBio, NULL, NULL, NULL);
if (pX509 == NULL)
/* error handling */
if( (cert_store= X509_STORE_new()) == NULL)
/* error handling */
if( (store_ctx= X509_STORE_CTX_new()) == NULL)
/* error handling */
/* edit1: this was wrong: don't add the certificate being verified to the trusted cert list */
/* if( !X509_STORE_add_cert(cert_store, pX509) ) */
/* error handling */
if( !X509_STORE_CTX_init(store_ctx, cert_store, CA, stack_of_x509) )
/* error handling */
X509_STORE_CTX_set_cert(store_ctx, pX509);
/* edit1: this was missing: set the verify time in order to check the certificate for expiry */
time(&check_time);
X509_STORE_CTX_set_time(store_ctx, 0, check_time);
X509_STORE_CTX_set_flags(store_ctx, X509_V_FLAG_USE_CHECK_TIME);
/* edit1: add callback function for ignoring self-signed error
* now, I'd like the validation to fail because of the expiry */
X509_STORE_set_verify_cb_func(store_ctx, cert_verify_callback);
switch( X509_verify_cert(store_ctx) ) {
/* the certificate is valid */
case 1:
printf("The certificate is valid\n");
break;
/* the certificate cannot be validated */
case -1:
case 0:
printf("The certificate is not valid\n");
store_ctx_error= X509_STORE_CTX_get_error(store_ctx);
store_ctx_error_depth= X509_STORE_CTX_get_error_depth(store_ctx);
printf("Error %d at %d depth: %s\n", store_ctx_error, store_ctx_error_depth, X509_verify_cert_error_string(store_ctx->error));
default:
break;
}
/* free data ... */
}
When validating the self-signed and expired certificate, my function prints:
Error 0 at 0 depth: ok
The function X509_STORE_add_cert() adds the corresponding certificate as a trusted certificate for verification, so this line:
X509_STORE_add_cert(cert_store, pX509)
says that your pX509 certificate is trusted for verification - but that's the certificate you want to test, so that's why a self-signed certificate is passing verification.
You also aren't setting a verification time - that's why an expired certificate is not being detected. Set the verification time with X509_STORE_CTX_set_time().

Resources