How to properly print error messages from `luaL_dostring()`? - error-handling

Here's my code that runs a Lua script as a string.
bool doString(const char *s)
{
const int ret = luaL_dostring(L, s);
if (ret)
{
if (ret == LUA_ERRSYNTAX)
printf("Error: %s", lua_tostring(L, -1));
else if (ret == LUA_ERRMEM)
printf("Error: memory error");
else
printf("Error: syntax error");
return false;
}
return true;
}
But in many cases, my code just prints Error: syntax error without any further description about where the error is happening.
How can I properly print the error messages so it can be more descriptive?

luaL_dostring returns LUA_OK /* 0 */ on success, and 1 on failure [1]. When it fails, it will push an error message on the stack describing the problem. This can be determined by following luaL_loadstring to lua_load in the docs [2]. Also, luaL_dostring invokes lua_pcall, which also pushes an error object on the stack when it fails (with no handler set) [3]
When you get a nonzero result, you can check the top of the stack for the error message and print that:
bool doString(const char *s) {
const int ret = luaL_dostring(L, s);
if (ret != LUA_OK) {
printf("Error: %s\n", lua_tostring(L, -1));
lua_pop(L, 1); // pop error message
return false;
}
return true;
}
[1] https://www.lua.org/manual/5.3/manual.html#luaL_dostring
[2] https://www.lua.org/manual/5.3/manual.html#lua_load
[3] https://www.lua.org/manual/5.3/manual.html#lua_pcall

Related

EXC_BAD_ACCESS error while using kinfo_proc

I a trying to get a list of running processes using KVM, BSD. But I'm getting an EXC_BAD_ACCESS error in my NSLog Statement. How do I deal with it?
int main(int argc, char *argv[]) {
#autoreleasepool {
struct kinfo_proc *procs;
size_t count;
int err = GetBSDProcessList(&procs, &count);
if (err) return err;
for (size_t i=0; i!=count; ++i) {
NSLog(#"%d\n", procs[i].kp_proc.p_pid);
}
free(procs);
}
}
Please help.
I don't know where did you get GetBSDProcessList function but with a litle bit of search I have found an implementation and following code works fine:
#import <Foundation/Foundation.h>
#import <sys/sysctl.h>
typedef struct kinfo_proc kinfo_proc;
static int GetBSDProcessList(kinfo_proc **procList, size_t *procCount);
int main(int argc, const char *argv[]) {
#autoreleasepool {
kinfo_proc *procList;
size_t count;
int err = GetBSDProcessList(&procList, &count);
if (err) return err;
for (size_t i = 0; i != count; ++i) {
NSLog(#"%d\n", procList[i].kp_proc.p_pid);
}
free(procList);
}
return 0;
}
static int GetBSDProcessList(kinfo_proc **procList, size_t *procCount)
// Returns a list of all BSD processes on the system. This routine
// allocates the list and puts it in *procList and a count of the
// number of entries in *procCount. You are responsible for freeing
// this list (use "free" from System framework).
// On success, the function returns 0.
// On error, the function returns a BSD errno value.
{
int err;
kinfo_proc *result;
bool done;
static const int name[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
// Declaring name as const requires us to cast it when passing it to
// sysctl because the prototype doesn't include the const modifier.
size_t length;
assert(procList != NULL);
assert(*procList == NULL);
assert(procCount != NULL);
*procCount = 0;
// We start by calling sysctl with result == NULL and length == 0.
// That will succeed, and set length to the appropriate length.
// We then allocate a buffer of that size and call sysctl again
// with that buffer. If that succeeds, we're done. If that fails
// with ENOMEM, we have to throw away our buffer and loop. Note
// that the loop causes use to call sysctl with NULL again; this
// is necessary because the ENOMEM failure case sets length to
// the amount of data returned, not the amount of data that
// could have been returned.
result = NULL;
done = false;
do {
assert(result == NULL);
// Call sysctl with a NULL buffer.
length = 0;
err = sysctl((int *) name, (sizeof(name) / sizeof(*name)) - 1,
NULL, &length,
NULL, 0);
if (err == -1) {
err = errno;
}
// Allocate an appropriately sized buffer based on the results
// from the previous call.
if (err == 0) {
result = malloc(length);
if (result == NULL) {
err = ENOMEM;
}
}
// Call sysctl again with the new buffer. If we get an ENOMEM
// error, toss away our buffer and start again.
if (err == 0) {
err = sysctl((int *) name, (sizeof(name) / sizeof(*name)) - 1,
result, &length,
NULL, 0);
if (err == -1) {
err = errno;
}
if (err == 0) {
done = true;
} else if (err == ENOMEM) {
assert(result != NULL);
free(result);
result = NULL;
err = 0;
}
}
} while (err == 0 && !done);
// Clean up and establish post conditions.
if (err != 0 && result != NULL) {
free(result);
result = NULL;
}
*procList = result;
if (err == 0) {
*procCount = length / sizeof(kinfo_proc);
}
assert((err == 0) == (*procList != NULL));
return err;
}
I am running this code on Mac OS X Mojave Beta 2 with Xcode 10 Beta 2 and here is somple console output:
.
.
.
2018-06-22 11:22:59.540990+0300 ProcessList[2407:96970] 58
2018-06-22 11:22:59.541040+0300 ProcessList[2407:96970] 55
2018-06-22 11:22:59.541057+0300 ProcessList[2407:96970] 54
2018-06-22 11:22:59.541067+0300 ProcessList[2407:96970] 52
2018-06-22 11:22:59.541075+0300 ProcessList[2407:96970] 51
2018-06-22 11:22:59.541084+0300 ProcessList[2407:96970] 49
2018-06-22 11:22:59.541092+0300 ProcessList[2407:96970] 47
2018-06-22 11:22:59.541101+0300 ProcessList[2407:96970] 46
2018-06-22 11:22:59.541109+0300 ProcessList[2407:96970] 45
2018-06-22 11:22:59.541134+0300 ProcessList[2407:96970] 42
2018-06-22 11:22:59.541257+0300 ProcessList[2407:96970] 41
2018-06-22 11:22:59.541280+0300 ProcessList[2407:96970] 1
2018-06-22 11:22:59.541290+0300 ProcessList[2407:96970] 0
Program ended with exit code: 0

OpenLDAP - Enabling CRL check for LDAP TLS connections

I have a client that connects to LDAP server using TLS. For this connection, I want to enable CRL check and reject the connection only if any server/client certificates are revoked.
In special cases (like CRL missing, CRL expired) I want to ignore the error and establish the connection.
So I though to overwrite the default SSL verify call back to ignore the specific errors.
But the call back is not called at all. Always only default call-back is called.
Here is my call back:
static int verify_callback(int ok, X509_STORE_CTX *ctx)
{
X509* cert = X509_STORE_CTX_get_current_cert(ctx);
if (ok)
return ok;
int sslRet = X509_STORE_CTX_get_error(ctx);
const char* err = NULL;
switch (sslRet)
{
case X509_V_ERR_UNABLE_TO_GET_CRL:
case X509_V_ERR_CRL_HAS_EXPIRED:
case X509_V_ERR_CRL_NOT_YET_VALID:
printf( "CRL: Verification failed... but ignored : %d\n", sslRet);
return 1;
default:
err = X509_verify_cert_error_string(sslRet);
if (err)
printf( "CRL: Failed to verify : %s\n",err);
return 0;
}
return sslRet;
}
Default verify call-back is overwritten using the ldap call-back set option:
void ldap_tls_cb(LDAP * ld, SSL * ssl, SSL_CTX * ctx, void * arg)
{
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER , verify_callback);
printf("verify call back is set...\n");
return;
}
Main Program:
int main( int argc, char **argv )
{
LDAP *ldap;
int auth_method = LDAP_AUTH_SIMPLE; //LDAP_AUTH_SASL
int ldap_version = LDAP_VERSION3;
char *ldap_host = "10.104.40.35";
int ldap_port = 389;
if ( (ldap = ldap_init(ldap_host, ldap_port)) == NULL ) {
perror( "ldap_init failed" );
return( EXIT_FAILURE );
}
int result = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ldap_version);
if (result != LDAP_OPT_SUCCESS ) {
ldap_perror(ldap, "ldap_set_option failed!");
return(EXIT_FAILURE);
}
int requireCert = LDAP_OPT_X_TLS_DEMAND;
result = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &requireCert);
if (result != LDAP_OPT_SUCCESS ) {
ldap_perror(ldap, "ldap_set_option - req cert -failed!");
return(EXIT_FAILURE);
}
result = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, "/etc/certs/Cert.pem");
if (result != LDAP_OPT_SUCCESS ) {
ldap_perror(ldap, "ldap_set_option - cert file - failed!");
return(EXIT_FAILURE);
}
int crlvalue = LDAP_OPT_X_TLS_CRL_ALL;
result =ldap_set_option(NULL, LDAP_OPT_X_TLS_CRLCHECK, &crlvalue);
if (result != LDAP_OPT_SUCCESS ) {
ldap_perror(ldap, "ldap_set_option failed!");
return(EXIT_FAILURE);
}
int debug = 7;
ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &debug);
result = ldap_set_option(ldap, LDAP_OPT_X_TLS_CONNECT_CB, (void *)ldap_tls_cb);
if (result != LDAP_SUCCESS) {
fprintf(stderr, "ldap_set_option(LDAP_OPT_X_TLS_CONNECT_CB): %s\n", ldap_err2string(result));
return(1);
}
int msgidp = 0;
result = ldap_start_tls(ldap,NULL,NULL,&msgidp);
if (result != LDAP_OPT_SUCCESS ) {
ldap_perror(ldap, "start tls failed!");
return result;
} else {
printf("Start tls success.\n");
}
LDAPMessage *resultm;
struct timeval timeout;
result = ldap_result(ldap, msgidp, 0, &timeout, &resultm );
if ( result == -1 || result == 0 ) {
printf("ldap_result failed;retC=%d \n", result);
return result;
}
result = ldap_parse_extended_result(ldap, resultm, NULL, NULL, 0 );
if ( result == LDAP_SUCCESS ) {
result = ldap_install_tls (ldap);
printf("installing tls... %s\n", ldap_err2string(result));
}
int request_id = 0;
result = ldap_sasl_bind(ldap, "", LDAP_SASL_SIMPLE, NULL, 0, 0, &request_id);
if ( result != LDAP_SUCCESS ) {
fprintf(stderr, "ldap_x_bind_s: %s\n", ldap_err2string(result));
printf("LDAP bind error .. %d\n", result);
return(EXIT_FAILURE);
} else {
printf("LDAP connection successful.\n");
}
ldap_unbind(ldap);
return(EXIT_SUCCESS);
}
can someone help to check why my verify call-back is not called?
I think you need to set the callback on the SSL object directly instead of the context, so
void ldap_tls_cb(LDAP * ld, SSL * ssl, SSL_CTX * ctx, void * arg)
{
SSL_set_verify(ssl, SSL_VERIFY_PEER, verify_callback);
printf("verify call back is set...\n");
return;
}
The reason for this is that the SSL handle has already been initialised by the time your connect callback is called (see the OpenLDAP code), and
it's too late to set this callback through the context at that point:
If no special callback was set before, the default callback for the underlying ctx is used, that was valid at the time ssl was created with SSL_new(3).
OpenLDAP can be built with GnuTLS, so you may need to check that it's using OpenSSL before setting the callback. The LDAP_OPT_X_TLS_PACKAGE option could be used for this (note that I haven't tested this code):
char* package = NULL;
int result = ldap_get_option(NULL, LDAP_OPT_X_TLS_PACKAGE, (void *)&package);
if (result != LDAP_OPT_SUCCESS) {
ldap_perror(ldap, "ldap_get_option failed!");
return(EXIT_FAILURE);
} else {
if (strcmp(package, "OpenSSL") == 0) {
// Set your callback
}
ldap_memfree(package);
}

libssh2: How to send data through libssh2_channel_write

EDIT:
Here's the complete code. modified the code to work with a router but the use case is same. Once i issue the password using libssh2_channel_write() subsequent libssh2_channel_read() fails with LIBSSH2_ERROR_SOCKET_RECV. Not sure why. I am unable to send subsequent commands to the remote device and get their output.
Logic was to execute a command on the remote device ( libssh2_channel_exec ). This command execution would throw a password to be entered by the client. Now read the stream via libssh2_channel_read() and ensure that the password is being asked and write the password to the channel via libssh2_channel_write(). Ensure the password is accepted on the remote device by doing subsequent reads [ THIS IS WHERE THE LIB IS FAILING WITH ERROR_SOCKET_RECV ] and then send the command to be executed via libssh2_channel_write() and read the command output. Am i missing something ?
for( ;; )
{
/* loop until we block */
int rc;
do
{
char buffer[0x4000];
rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
if( rc > 0 )
{
int i;
char *enable = "check-password\n";
int ret;
bytecount += rc;
fprintf(stderr, "We read [%d] bytes:\n", bytecount);
fputc('[', stderr);
for( i=0; i < rc; ++i )
fputc( buffer[i], stderr);
fputc(']', stderr);
if ( strstr(buffer, "Password:") != NULL ){
fprintf(stderr, "Sending the password now\n");
while((ret = libssh2_channel_write(channel, enable, strlen(enable))) == LIBSSH2_ERROR_EAGAIN) {
printf("ERROR_EAGAIN - sending password again\n");
}
fprintf(stderr, "Wrote [%d] bytes: \n", ret);
flag = 1;
continue;
}
if (!flag){ // start
char *cmd = "show clock\n";
int ret;
fprintf(stderr, "THIS Fetching show clock command now\n");
while((ret = libssh2_channel_write(channel, cmd, strlen(cmd))) == LIBSSH2_ERROR_EAGAIN) {
printf("ERROR_EAGAIN - sending show clock again\n");
}
flag = 1;
} // end
}
else {
if(rc != LIBSSH2_ERROR_EAGAIN)
fprintf(stderr, "libssh2_channel_read returned [%d]:\n ", rc);
}
}
while( rc > 0 );
/* this is due to blocking that would occur otherwise so we loop on
this condition */
if( rc == LIBSSH2_ERROR_EAGAIN )
{
int check;
check = waitsocket(sock, session);
}
else
break;
}

openssl BIO_do_connect returns 0 for ssl

Here's my simple openssl client test case trying to connect to google.com:443.
According to the manual, BIO_do_connect should return 1, 0 or -1.
Google didn't find me anyone for whom it returns 0, which it does for me.
#include <stdio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
int main()
{
SSL_load_error_strings();
SSL_library_init();
ERR_load_BIO_strings();
OpenSSL_add_all_algorithms();
SSL_CTX *p_ssl_ctx = NULL;
SSL *p_ssl = NULL;
BIO * bio = NULL;
int r = 0;
// init ssl context
p_ssl_ctx = SSL_CTX_new(SSLv2_client_method()); /* Create new context */
if (p_ssl_ctx == NULL)
{
ERR_print_errors_fp(stderr);
return 3;
}
const char *store_path = "/etc/ssl/certs/ca-certificates.crt";
r = SSL_CTX_load_verify_locations(p_ssl_ctx, store_path, NULL);
if (r == 0) {
fprintf(stderr, "Unable to load the trust store from %s.\n", store_path);
return 4;
}
bio = BIO_new_ssl_connect(p_ssl_ctx);
if (!bio) {
fprintf(stderr, "no bio \n");
return 5;
}
BIO_get_ssl(bio, &p_ssl);
if (!(p_ssl)) {
fprintf(stderr, "no ssl\n");
return 6;
}
SSL_set_mode(p_ssl, SSL_MODE_AUTO_RETRY);
BIO_set_conn_hostname(bio, "www.google.com:443");
r = BIO_do_connect(bio);
if (r < 1) {
fprintf(stderr, "BIO_new_ssl_connect failed: %lu (0x%lx)\n", r, r);
fprintf(stderr, "Error: %s\n", ERR_reason_error_string(ERR_get_error()));
fprintf(stderr, "%s\n", ERR_error_string(ERR_get_error(), NULL));
ERR_print_errors_fp(stderr);
perror("bio");
return 7;
}
if (SSL_get_verify_result(p_ssl) != X509_V_OK) {
fprintf(stderr, "Unable to verify connection result.\n");
return 8;
}
return 0;
}
returns:
BIO_new_ssl_connect failed: 0 (0x0)
Error: (null)
error:00000000:lib(0):func(0):reason(0)
bio: Success
so how do i get the actual error out of this?
For getting the last state of your SSL connection in your code you can add something like fprintf(stderr,"p_ssl state: %s\n",SSL_state_string_long(p_ssl));.
More generally I suggest you to add an info callback like this : http://www.openssl.org/docs/ssl/SSL_CTX_set_info_callback.html
For your case, you must replace SSLv2_client_method() by something like TLSv1_client_method().

TinyOS periodic Bcast AMSend not received

I want to send messages periodically through this program, the messages are broadcasted fine and I get a sendDone message. The problem is that these messages are not received well. I would really appreciate any help to find out where the problem is?
Here is the code(please ignore unused variables as I have cut a lot of the code):
includes lqer;
module lqer_M{
provides {
interface SplitControl;
interface AMSend[am_id_t id];
interface Receive[uint8_t id];
};
uses {
interface SplitControl as AMControl;
interface Timer<TMilli> as LQERTimer;
interface Random;
interface AMPacket;
interface AMSend as SendPacket;
interface Receive as ReceivePacket;
interface PacketAcknowledgements;
interface Packet;
}
}
implementation{
message_t lqer_msg_;
message_t* p_lqer_msg_;
lqer_table l_table[LQER_FT_SIZE];
node_info info;
uint8_t max=0, Pos=0;
message_t* newADV;
bool busy = FALSE;
command error_t SplitControl.start() {
int i,j;
p_lqer_msg_ = &lqer_msg_;
info.hop=1000;
for(i=0; i<16; i++){
info.m[i]=1;
}
for(i = 0; i< LQER_FT_SIZE; i++) {
l_table[i].nid = INVALID_NODE_ID;
l_table[i].hop = 1000;
for (j=0; j<16; j++)
{
l_table[i].m[j]=1;
}
}
call AMControl.start();
return SUCCESS;
}
command error_t SplitControl.stop() {
call AMControl.stop();
return SUCCESS;
}
event void AMControl.startDone( error_t e ) {
if ( e == SUCCESS ) {
call LQERTimer.startPeriodic( LQER_DEFAULT_PERIOD );
signal SplitControl.startDone(e);
} else {
call AMControl.start();
}
}
event void AMControl.stopDone(error_t e){
call LQERTimer.stop();
signal SplitControl.stopDone(e);
}
event void LQERTimer.fired() {
message_t* lqer_adv_msg;
lqer_adv_hdr* new_ADV=(lqer_adv_hdr*)(lqer_adv_msg->data);
am_addr_t me = call AMPacket.address();
if (me==0001){
new_ADV->src = me;
new_ADV->hop = 0;
newADV= (message_t*)(&new_ADV);
dbg("GRAPE_DBG", "%s\t LQER: Sink address: %d\n", sim_time_string(), me);
call PacketAcknowledgements.requestAck(newADV);
call SendPacket.send( AM_BROADCAST_ADDR, newADV, call Packet.payloadLength(newADV) );
}
}
event message_t* ReceivePacket.receive( message_t* p_msg, void* payload, uint8_t len ) {
lqer_adv_hdr* lqer_hdr = (lqer_adv_hdr*)(p_msg->data);
lqer_adv_hdr* msg_lqer_hdr =(lqer_adv_hdr*)(p_lqer_msg_->data);
uint8_t i;
lqer_adv_hdr* new_ADV =(lqer_adv_hdr*)(p_lqer_msg_->data);
dbg("GRAPE_DBG", "%s\t ADV: RecievedADV dst: \n", sim_time_string());
msg_lqer_hdr->src = lqer_hdr->src;
msg_lqer_hdr->hop = lqer_hdr->hop;
new_ADV->src = msg_lqer_hdr->src;
new_ADV->hop = msg_lqer_hdr->hop;
newADV= (message_t*)(&new_ADV);
call PacketAcknowledgements.requestAck( newADV );
call SendPacket.send( AM_BROADCAST_ADDR, newADV, call Packet.payloadLength(newADV) );
return p_msg;
}
command error_t AMSend.cancel[am_id_t id](message_t* msg) {
return call SendPacket.cancel(msg);
}
command uint8_t AMSend.maxPayloadLength[am_id_t id]() {
return call Packet.maxPayloadLength();
}
command void* AMSend.getPayload[am_id_t id](message_t* m, uint8_t len) {
return call Packet.getPayload(m, 0);
}
default event void AMSend.sendDone[uint8_t id](message_t* msg, error_t err) {
return;
}
default event message_t* Receive.receive[am_id_t id](message_t* msg, void* payload, uint8_t len) {
return msg;
}
command error_t AMSend.send[am_id_t id](am_addr_t addr, message_t* msg, uint8_t len)
{
call SendPacket.send( TOS_BCAST_ADDR , msg, call Packet.payloadLength(msg) );
return SUCCESS;
}
event void SendPacket.sendDone(message_t* p_msg, error_t e) {
dbg("GRAPE_DBG", "%s\t ADV: SendDone\n", sim_time_string());
if( p_msg== newADV)
busy=FALSE;
}
}
You should look at what is the error value in the sendDone event. It is possible that send returns success, but the sending fail after that, and the error code is returned in the sendDone. These error includes ENOACK, ENOMEM, etc.
Also, check your destination address and the AM address of the receiver.