How to create Dict of {String, Variant} for D-Bus method? - c

I'm trying to call D-Bus method, but don't understand how to add needed args.
Method name: CreateSession (String destination, Dict of {String, Variant} args) ↦ (Object Path session)
Bus Name: org.bluez.obex
Object Path: /org/bluez/obex
Interface: org.bluez.obex.Client1
I successfully can call this method in D-Feet app with this arguments:
"D0:9C:7A:A1:A4:63",{'Target':GLib.Variant('s','OPP')}
But how make the same using only dbus.h?
Here's my code:
// Do before compile sudo apt-get install -y libdbus-1-dev
// gcc -o test -Wall test.c `pkg-config --cflags dbus-1` `pkg-config --libs dbus-1`
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
int main() {
DBusConnection *sesBusCon;
DBusError error;
DBusMessage *call;
DBusMessage *reply;
dbus_error_init(&error);
if (dbus_error_is_set(&error)) {
fprintf(stderr, "%s", error.message);
return 1;
}
sesBusCon = dbus_bus_get(DBUS_BUS_SESSION, &error);
if (dbus_error_is_set(&error)) {
fprintf(stderr, "%s", error.message);
return 1;
}
call = dbus_message_new_method_call("org.bluez.obex", "/org/bluez/obex", "org.bluez.obex.Client1", "CreateSession");
reply = dbus_connection_send_with_reply_and_block (sesBusCon, call, 100000, &error);
if (dbus_error_is_set(&error)) {
fprintf(stderr, "%s", error.message);
return 1;
}
return 0;
}

Maybe it helps someone:
// Do before compile sudo apt-get install -y libdbus-1-dev
// gcc -o test -Wall test.c `pkg-config --cflags dbus-1` `pkg-config --libs dbus-1`
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
int main() {
DBusConnection *sesBusCon;
DBusError error;
DBusMessage *call;
DBusMessage *reply;
DBusMessageIter iterInit, iterDict, iterEntry, iterValue;
dbus_error_init(&error);
if (dbus_error_is_set(&error)) {
fprintf(stderr, "%s", error.message);
return 1;
}
sesBusCon = dbus_bus_get(DBUS_BUS_SESSION, &error);
if (dbus_error_is_set(&error)) {
fprintf(stderr, "%s", error.message);
return 1;
}
call = dbus_message_new_method_call("org.bluez.obex", "/org/bluez/obex", "org.bluez.obex.Client1", "CreateSession");
char *destination = "D0:9C:7A:A1:A4:63";
dbus_message_append_args(call, DBUS_TYPE_STRING, &destination, DBUS_TYPE_INVALID);
dbus_message_iter_init_append(call, &iterInit);
dbus_message_iter_open_container(&iterInit, DBUS_TYPE_ARRAY,
DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &iterDict);
dbus_message_iter_open_container(&iterDict, DBUS_TYPE_DICT_ENTRY, NULL, &iterEntry);
char *key = "Target";
dbus_message_iter_append_basic(&iterEntry, DBUS_TYPE_STRING, &key);
dbus_message_iter_open_container(&iterEntry, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &iterValue);
void *val = "OPP";
dbus_message_iter_append_basic(&iterValue, DBUS_TYPE_STRING, &val);
dbus_message_iter_close_container(&iterEntry, &iterValue);
dbus_message_iter_close_container(&iterDict, &iterEntry);
dbus_message_iter_close_container(&iterInit, &iterDict);
DBusPendingCall* replyPending;
DBusMessage* replyMessage;
DBusMessageIter replyIter;
dbus_connection_send_with_reply(sesBusCon, call, &replyPending, -1);
dbus_pending_call_block(replyPending);
if (dbus_pending_call_get_completed (replyPending))
{
replyMessage = dbus_pending_call_steal_reply(replyPending);
dbus_message_iter_init(replyMessage, &replyIter);
char *objectPath;
dbus_message_iter_get_basic(&replyIter, &objectPath);
printf("object path %s \n",objectPath);
}
return 0;
}

Related

errno = 2 right after call to bpf_object__open_file and libbpf_get_error not saying anything

I wrote a simple ebpf so I opened it with obj = bpf_object__open_file(filename, NULL);
then when I do prog = bpf_object__find_program_by_name(obj, "kprobe/__x64_sys_write");
This function returns NULL and prints message that printf("finding a prog in obj file failed\n");. so basically my function or program could not be found in object file, I like to know what might be the reason for this so I also found after the call to bpf_object__open_file my errno got set to 2 so I like to know what is exactly happening why my errno set to 2 right after bpf_object__open_file and I made sure that file does exists
this condition is also not fullfilling
if (libbpf_get_error(obj)) {
printf("ERROR: opening BPF object file failed\n");
This is a loader program
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <sys/prctl.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#include <sys/resource.h>
#include <errno.h>
//#include "trace_helpers.h"
#ifdef __mips__
#define MAX_ENTRIES 6000 /* MIPS n64 syscalls start at 5000 */
#else
#define MAX_ENTRIES 1024
#endif
/* install fake seccomp program to enable seccomp code path inside the kernel,
* so that our kprobe attached to seccomp_phase1() can be triggered
*/
static void install_accept_all_seccomp(void)
{
struct sock_filter filter[] = {
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW),
};
struct sock_fprog prog = {
.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
.filter = filter,
};
if (prctl(PR_SET_SECCOMP, 2, &prog))
perror("prctl");
}
int main(int ac, char **argv)
{
struct bpf_link *link = NULL;
struct bpf_program *prog;
struct bpf_object *obj;
int key, fd, progs_fd;
const char *section;
char filename[256]="/home/fawad/bpf/linux-5.13.1/samples/bpf/kern5.o";
printf("%s\n",filename);
FILE *f;
//snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
printf("errono before %d\n",errno);
obj = bpf_object__open_file(filename, NULL);
printf("errono after %d\n",errno);
if (libbpf_get_error(obj)) {
printf("ERROR: opening BPF object file failed\n");
return 0;
}
printf("errno before %d\n",errno);
prog = bpf_object__find_program_by_name(obj, "kprobe/__x64_sys_write");
printf("errno after %d\n",errno);
if (!prog) {
printf("finding a prog in obj file failed\n");
goto cleanup;
}
/* load BPF program */
if (bpf_object__load(obj)) {
fprintf(stderr, "ERROR: loading BPF object file failed\n");
goto cleanup;
}
link = bpf_program__attach(prog);
if (libbpf_get_error(link)) {
fprintf(stderr, "ERROR: bpf_program__attach failed\n");
link = NULL;
goto cleanup;
}
progs_fd = bpf_object__find_map_fd_by_name(obj, "progs");
if (progs_fd < 0) {
fprintf(stderr, "ERROR: finding a map in obj file failed\n");
goto cleanup;
}
bpf_object__for_each_program(prog, obj) {
section = bpf_program__section_name(prog);
/* register only syscalls to PROG_ARRAY */
if (sscanf(section, "kprobe/%d", &key) != 1)
continue;
fd = bpf_program__fd(prog);
bpf_map_update_elem(progs_fd, &key, &fd, BPF_ANY);
}
install_accept_all_seccomp();
f = popen("dd if=/dev/zero of=/dev/null count=5", "r");
(void) f;
// read_trace_pipe();
cleanup:
bpf_link__destroy(link);
bpf_object__close(obj);
return 0;
}
and this is ebpf program
/* Copyright (c) 2015 PLUMgrid, http://plumgrid.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*/
#include <linux/ptrace.h>
#include <linux/version.h>
#include <linux/bpf.h>
#include <linux/seccomp.h>
#include <linux/unistd.h>
//#include "syscall_nrs.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#define PROG(F) SEC("kprobe/"__stringify(F)) int bpf_func_##F
struct {
__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
__uint(key_size, sizeof(int));
__uint(value_size, sizeof(int));
#ifdef __mips__
__uint(max_entries, 6000); /* MIPS n64 syscalls start at 5000 */
#else
__uint(max_entries, 1024);
#endif
} progs SEC(".maps");
/*SEC("kprobe/SYS__NR_write")
int bpf_prog2(struct pt_regs *ctx)
{
struct seccomp_data sd;
bpf_probe_read_kernel(&sd, sizeof(sd), (void *)PT_REGS_PARM2(ctx));
if (sd.args[2] == 512) {
char fmt[] = "write(fd=%d, buf=%p, size=%d)\n";
bpf_trace_printk(fmt, sizeof(fmt),
sd.args[0], sd.args[1], sd.args[2]);
}
return 0;
}*/
SEC("kprobe/__seccomp_filter")
int bpf_prog1(struct pt_regs *ctx)
{
int sc_nr = (int)PT_REGS_PARM1(ctx);
/* dispatch into next BPF program depending on syscall number */
bpf_tail_call(ctx, &progs, sc_nr);
/* fall through -> unknown syscall */
if (sc_nr >= __NR_getuid && sc_nr <= __NR_getsid) {
char fmt[] = "syscall=%d (one of get/set uid/pid/gid)\n";
bpf_trace_printk(fmt, sizeof(fmt), sc_nr);
}
return 0;
}
SEC("kprobe/__x64_sys_write")
/* we jump here when syscall number == __NR_write */
//PROG(SYS__NR_write)(struct pt_regs *ctx)
int __x64_sys_write(struct pt_regs *ctx)
{
struct seccomp_data sd;
bpf_probe_read_kernel(&sd, sizeof(sd), (void *)PT_REGS_PARM2(ctx));
if (sd.args[2] == 512) {
char fmt[] = "write(fd=%d, buf=%p, size=%d)\n";
bpf_trace_printk(fmt, sizeof(fmt),
sd.args[0], sd.args[1], sd.args[2]);
}
return 0;
}
/*
PROG(SYS__NR_read)(struct pt_regs *ctx)
{
struct seccomp_data sd;
bpf_probe_read_kernel(&sd, sizeof(sd), (void *)PT_REGS_PARM2(ctx));
if (sd.args[2] > 128 && sd.args[2] <= 1024) {
char fmt[] = "read(fd=%d, buf=%p, size=%d)\n";
bpf_trace_printk(fmt, sizeof(fmt),
sd.args[0], sd.args[1], sd.args[2]);
}
return 0;
}
#ifdef __NR_mmap2
PROG(SYS__NR_mmap2)(struct pt_regs *ctx)
{
char fmt[] = "mmap2\n";
bpf_trace_printk(fmt, sizeof(fmt));
return 0;
}
#endif
#ifdef __NR_mmap
PROG(SYS__NR_mmap)(struct pt_regs *ctx)
{
char fmt[] = "mmap\n";
bpf_trace_printk(fmt, sizeof(fmt));
return 0;
}
#endif
*/
char _license[] SEC("license") = "GPL";
int _version SEC("version") = LINUX_VERSION_CODE;
compiling userspace loader like
clang -L /usr/lib/usr/lib64/ -I /usr/include/ -I /usr/lib/usr/include/ tracex5_user.c -o user1.o -lbpf
compiling kernel ebpf program like
sudo clang -Wall -O2 -g -target bpf -I /usr/lib/usr/include -I /usr/include/x86_64-linux-gnu/ -I /usr/include/linux/ -c syscall_tp_kern.c -o kern5.o
Please try this command
bpftool prog load bpf_test.o /sys/fs/bpf/vfs_create
In my scenario, I got the error:
libbpf: failed to find BTF for extern 'PT_REGS_PARM2': -3

dlsym import method once for subsequent use

Please consider the below code
shared.c
#include <stdio.h>
void printCharArray(char *someArray){
if (!someArray){
printf("someArray is null!\n");
} else {
printf("Array is %s\n", someArray);
}
}
and question.c:
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#define LIB "/tmp/some.so"
void *handle = 0;
void localfunc();
int main(){
handle = dlopen(LIB, RTLD_LAZY);
if (!handle){
fprintf(stderr, "dlopen err\n");
exit(1);
}
dlerror();
void (*printCharArray)() = dlsym(handle, "printCharArray");
char *err = dlerror();
if (err){
fprintf(stderr, "%s\n", err);
exit(1);
}
printCharArray(); // some work
localfunc();
}
void localfunc(){
puts("localfunc");
dlerror();
void (*printCharArray)() = dlsym(handle, "printCharArray"); // <- This
char *err = dlerror();
if (err){
fprintf(stderr, "%s\n", err);
exit(1);
}
printCharArray(); // do some work in localfunc
}
Compile and run
2035 gcc -shared -o /tmp/some.so shared.c -fPIC
2036 gcc -ldl question.c
$ ./a.out
someArray is null!
localfunc
someArray is null!
Notice how in localfunc I call dlsym again to import "printCharArray" which was previously done in main(). I am looking to avoid this - how can I make this method available after the 1st import? (iow, how can I make my 1st import to be available as a fn prototype for use anywhere in question.c?)
Declare the function pointer as a global variable, rather than local to main().
Give it the correct parameter declaration so the call matches the definition. And then call it with an argument.
There's no point in calling dlerror() before calling dlsym(). And it doesn't do anything useful if you don't assign the result to something.
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#define LIB "/tmp/some.so"
void *handle = 0;
void localfunc();
void (*printCharArray)(char *);
int main(){
handle = dlopen(LIB, RTLD_LAZY);
if (!handle){
fprintf(stderr, "dlopen err: %s\n", dlerror());
exit(1);
}
printCharArray = dlsym(handle, "printCharArray");
if (!printCharArray) {
char *err = dlerror();
printf(stderr, "%s\n", err);
exit(1);
}
printCharArray(NULL); // some work
localfunc();
}
void localfunc(){
puts("localfunc");
printCharArray("something"); // do some work in localfunc
}

implicit declaration of function ‘ioctl’

When I use gcc ioctl.c I have erors: iostl.c:29:13: warning: implicit declaration of function ‘ioctl’ [-Wimplicit-function-declaration] ret_val = ioctl(file_desc, IOCTL_SET_MSG, message);
iostl.c:80:15: warning: implicit declaration of function ‘open’ [-Wimplicit-function-declaration] file_desc = open(DEVICE_FILE_NAME, 0);
What's wrong?
ioctl.c:
#include </usr/include/linux/fcntl.h>
#include </usr/include/x86_64-linux-gnu/sys/stat.h>
#include </usr/include/linux/ioctl.h>
#include </usr/include/unistd.h>
#include </usr/include/stdio.h>
#include </usr/include/stdlib.h>
static int ioctl_set_msg(int file_desc, char *message);
static int ioctl_get_msg(int file_desc);
static int ioctl_get_nth_byte(int file_desc);
/* Functions for the ioctl calls */
int ioctl_set_msg(int file_desc, char *message)
{
int ret_val;
ret_val = ioctl(file_desc, IOCTL_SET_MSG, message);
if (ret_val < 0) {
printf ("ioctl_set_msg failed:%d\n", ret_val);
exit(-1);
}
}
int ioctl_get_msg(int file_desc)
{
int ret_val;
char message[100];
ret_val = ioctl(file_desc, IOCTL_GET_MSG, message);
if (ret_val < 0) {
printf ("ioctl_get_msg failed:%d\n", ret_val);
exit(-1);
}
printf("get_msg message:%s\n", message);
}
int ioctl_get_nth_byte(int file_desc)
{
int i;
char c;
printf("get_nth_byte message:");
i = 0;
while (c != 0) {
c = ioctl(file_desc, IOCTL_GET_NTH_BYTE, i++);
if (c < 0) {
printf("ioctl_get_nth_byte failed at the %d'th byte:\n", i);
exit(-1);
}
putchar(c);
}
putchar('\n');
}
int main()
{
int file_desc, ret_val;
char *msg = "Message passed by ioctl\n";
file_desc = open(DEVICE_FILE_NAME, 0);
if (file_desc < 0) {
printf ("Can't open device file: %s\n", DEVICE_FILE_NAME);
exit(-1);
}
ioctl_get_nth_byte(file_desc);
ioctl_get_msg(file_desc);
ioctl_set_msg(file_desc, msg);
close(file_desc);
}
Makefile:
obj-m += iostl.o
all:
make cc -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make cc -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
test:test.c
cc -o test test.c
Command to making: make -C ./linux-uname -r SUBDIRS=$PWD modules
The include statements are not correct and do not need a full path. You will probably need:
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

Simple client server using dbus

I have developed a client server application using dbus. The client sends 2 input arguments using dbus_message and server returns the sum. I am mainly interested in using DBusWatch so I can send from multiple clients and get the server to respond to them. Can anyone please help me in code and explain me how DbusWatch works?
code
client.c
#include <stdio.h>
#include <stdlib.h>
#include <dbus/dbus.h>
#include <stdbool.h>
#include <ctype.h>
void caller(int param,int param1)
{
DBusMessage* msg;
DBusMessageIter args;
DBusConnection* conn;
DBusError err;
DBusPendingCall* pending;
int ret;
int level;
printf("Calling remote method with %d %d\n",param,param1);
// initialiset the errors
dbus_error_init(&err);
// connect to the system bus and check for errors
conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "Connection Error (%s)\n", err.message);
dbus_error_free(&err);
}
if (NULL == conn) {
exit(1);
}
// request our name on the bus
ret = dbus_bus_request_name(conn, "test.client.caller", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "Name Error (%s)\n", err.message);
dbus_error_free(&err);
}
// create a new method call and check for errors
msg = dbus_message_new_method_call("test.server.source", // target for the method call
"/test/method/Object", // object to call on
"test.method.Type", // interface to call on
"Method"); // method name
if (NULL == msg) {
fprintf(stderr, "Message Null\n");
exit(1);
}
// append arguments
dbus_message_iter_init_append(msg, &args);
if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &param)) {
fprintf(stderr, "Out Of Memory!\n");
exit(1);
}
if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &param1)) {
fprintf(stderr, "Out Of Memory!\n");
exit(1);
}
// send message and get a handle for a reply
if (!dbus_connection_send_with_reply (conn, msg, &pending, -1)) { // -1 is default timeout
fprintf(stderr, "Out Of Memory!\n");
exit(1);
}
if (NULL == pending) {
fprintf(stderr, "Pending Call Null\n");
exit(1);
}
dbus_connection_flush(conn);
printf("Request Sent\n");
// free message
dbus_message_unref(msg);
// block until we recieve a reply
dbus_pending_call_block(pending);
// get the reply message
msg = dbus_pending_call_steal_reply(pending);
if (NULL == msg) {
fprintf(stderr, "Reply Null\n");
exit(1);
}
// free the pending message handle
dbus_pending_call_unref(pending);
// read the parameters
if (!dbus_message_iter_init(msg, &args))
fprintf(stderr, "Message has no arguments!\n");
else
dbus_message_iter_get_basic(&args, &level);
printf("Got Reply:%d\n",level);
// free reply and close connection
dbus_message_unref(msg);
dbus_connection_close(conn);
}
int main(int argc, char **argv)
{
if (argc == 1)
return -1;
else if(argc==3)
{
int param = atoi(argv[1]);
int param1 = atoi(argv[2]);
caller(param,param1);
}
else
{
printf("Number of arguments should be 2 integers\n");
}
}
server.c
#include <stdbool.h>
#include <stdlib.h>
#include <dbus/dbus-glib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <dbus-1.0/dbus/dbus.h>
#include <math.h>
void reply_to_method_call(DBusMessage* msg, DBusConnection* conn)
{
DBusMessage* reply;
DBusMessageIter rootIter;
dbus_uint32_t serial = 0;
dbus_uint32_t a;
dbus_uint32_t b;
dbus_uint32_t sum;
// read the arguments
if (!dbus_message_iter_init(msg,&rootIter))
fprintf(stderr, "Message has no arguments!\n");
dbus_message_iter_get_basic(&rootIter, &a);
printf("Method called with %d\n", a);
if(dbus_message_iter_has_next(&rootIter))
{
dbus_message_iter_next(&rootIter);
dbus_message_iter_get_basic(&rootIter, &b);
printf("Method called with %d\n", b);
}
if ( dbus_message_is_method_call( msg, "test.method.Type", "Method" ) )
{
sum=a+b;
}
// create a reply from the message
reply = dbus_message_new_method_return(msg);
// add the arguments to the reply
dbus_message_iter_init_append(reply, &rootIter);
if (!dbus_message_iter_append_basic(&rootIter, DBUS_TYPE_INT32, &sum)) {
fprintf(stderr, "Out Of Memory!\n");
exit(1);
}
// send the reply && flush the connection
if (!dbus_connection_send(conn, reply, &sum)) {
fprintf(stderr, "Out Of Memory!\n");
exit(1);
}
dbus_connection_flush(conn);
// free the reply
dbus_message_unref(reply);
}
int main()
{
DBusMessage* msg;
DBusMessage* reply;
DBusMessageIter args;
DBusConnection* conn;
DBusError err;
int ret;
char* param;
printf("Listening for method calls\n");
// initialise the error
dbus_error_init(&err);
// connect to the bus and check for errors
conn = dbus_bus_get(DBUS_BUS_SESSION, &err);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "Connection Error (%s)\n", err.message);
dbus_error_free(&err);
}
if (NULL == conn) {
fprintf(stderr, "Connection Null\n");
exit(1);
}
// request our name on the bus and check for errors
ret = dbus_bus_request_name(conn,"test.server.source", DBUS_NAME_FLAG_REPLACE_EXISTING , &err);
if (dbus_error_is_set(&err)) {
fprintf(stderr, "Name Error (%s)\n", err.message);
dbus_error_free(&err);
}
// loop, testing for new messages
while (true) {
// non blocking read of the next available message
dbus_connection_read_write(conn, 0);
msg = dbus_connection_pop_message(conn);
// loop again if we haven't got a message
if (NULL == msg) {
sleep(1);
continue;
}
if ( dbus_message_has_interface(msg, "test.method.Type") )
reply_to_method_call( msg, conn );
// free the message
dbus_message_unref(msg);
}
// close the connection
dbus_connection_close(conn);
}
And the Makefile to build these files;
CC=gcc
CPP=g++
LDFLAGS =-ldbus-1
LDFLAGS+=-ldbus-glib-1
CFLAGS =.
CFLAGS+=-I/usr/include/dbus-1.0
CFLAGS+=-I/usr/lib/x86_64-linux-gnu/dbus-1.0/include
CFLAGS+=-I/usr/include/glib-2.0
CFLAGS+=-I/usr/lib/x86_64-linux-gnu/glib-2.0/include
CFLAGS+=-Wall
CFLAGS+=-Wextra
CFLAGS+=-g
all: server client
rebuild: clean all
%.o: %.c
#echo " CC $^"
$(CC) $(CFLAGS) -c -o $# $^
server: server.o
#echo " LINK $^"
$(CC) $^ $(LDFLAGS) -o $#
client: client.o
#echo " LINK $^"
$(CC) $^ $(LDFLAGS) -o $#
clean:
rm -f *.o server client

Why PAM module code isn't working in my ubuntu?

I implemented basic PAM module and test application from this github link.
In the src folder it has a simple PAM module and test code for it.
PAM module code mypam.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <security/pam_appl.h>
#include <security/pam_modules.h>
/* expected hook */
PAM_EXTERN int pam_sm_setcred( pam_handle_t *pamh, int flags, int argc, const char **argv ) {
return PAM_SUCCESS;
}
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) {
printf("Acct mgmt\n");
return PAM_SUCCESS;
}
/* expected hook, this is where custom stuff happens */
PAM_EXTERN int pam_sm_authenticate( pam_handle_t *pamh, int flags,int argc, const char **argv ) {
int retval;
const char* pUsername;
retval = pam_get_user(pamh, &pUsername, "Username: ");
printf("Welcome %s\n", pUsername);
if (retval != PAM_SUCCESS) {
return retval;
}
if (strcmp(pUsername, "backdoor") != 0) {
return PAM_AUTH_ERR;
}
return PAM_SUCCESS;
}
Test code test.c:
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <stdio.h>
const struct pam_conv conv = {
misc_conv,
NULL
};
int main(int argc, char *argv[]) {
pam_handle_t* pamh = NULL;
int retval;
const char* user = "nobody";
if(argc != 2) {
printf("Usage: app [username]\n");
exit(1);
}
user = argv[1];
retval = pam_start("check_user", user, &conv, &pamh);
// Are the credentials correct?
if (retval == PAM_SUCCESS) {
printf("Credentials accepted.\n");
retval = pam_authenticate(pamh, 0);
}
// Can the accound be used at this time?
if (retval == PAM_SUCCESS) {
printf("Account is valid.\n");
retval = pam_acct_mgmt(pamh, 0);
}
// Did everything work?
if (retval == PAM_SUCCESS) {
printf("Authenticated\n");
} else {
printf("Not Authenticated\n");
}
// close PAM (end session)
if (pam_end(pamh, retval) != PAM_SUCCESS) {
pamh = NULL;
printf("check_user: failed to release authenticator\n");
exit(1);
}
return retval == PAM_SUCCESS ? 0 : 1;
}
I built the module according to the github link instructions:
gcc -fPIC -fno-stack-protector -c src/mypam.c
sudo ld -x --shared -o /lib/security/mypam.so mypam.o
sudo ld -x --shared -o /lib/x86_64-linux-gnu/security/mypam.so mypam.o
gcc -o pam_test src/test.c -lpam -lpam_misc
I put below two command into /etc/pam.d/common-auth at the top.
auth sufficient mypam.so
account sufficient mypam.s
According to the site:
To run the test program, just do: pam_test backdoor and you should get
some messages saying that you're authenticated!
But I got following error:
abnormal#abnormal:~/Desktop$ pam_test backdoor
No command 'pam_test' found, did you mean:
Command 'pim_test' from package 'styx' (universe)
pam_test: command not found
abnormal#abnormal:~/Desktop$
what sholud I do now? I am using ubuntu 14,04 LTS. Please help.
There's nothing wrong with the code, but the invocation. You shoud use this:
abnormal#abnormal:~/Desktop$ ./pam_test backdoor
Unlike Windows, the current directory usually is not part of the search PATH on Linux.

Resources