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

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.

Related

How to check password on macOS?

The following C program can check the password of a user on Linux.
But it does not work on macOS because some functions are Linux specific.
Could anybody show me how to revise the program so that it works on macOS?
#include <unistd.h>
#include <pwd.h>
#include <shadow.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
char *username = argv[1];
struct passwd *pwd = getpwnam(username);
if (pwd == NULL) {
fputs("couldn't get password record", stderr);
return 1;
}
struct spwd *spwd = getspnam(username);
if (spwd == NULL) {
if(errno == EACCES) {
fputs("no permission to read shadow password file", stderr);
return 1;
}
fputs("No such username", stderr);
return 1;
}
char *password = getpass("Password: ");
printf("spwd->sp_pwdp: %s\n", spwd->sp_pwdp);
char *encrypted = crypt(password, spwd->sp_pwdp);
for (char *p = password; *p != '\0'; ++p)
*p = '\0';
if (encrypted == NULL) {
perror("crypt");
return 1;
}
if (strcmp(encrypted, spwd->sp_pwdp) != 0) {
fputs("Incorrect password\n", stderr);
return 1;
}
printf("Successfully authenticated: UID=%d\n", pwd->pw_uid);
return 0;
}
$ sudo ./checkpass "$USER"
Password:
spwd->sp_pwdp: $y$j9T$F5Jx5fExrKuPp53xLKQ..1$X3DX6M94c7o.9agCG9G317fhZg9SqC.5i5rd.RhAtQ7
Successfully authenticated: UID=504
Both Linux and macOS use PAM for authentication; Linux uses Linux-PAM, and MacOS and BSDs OpenPAM.
To authenticate via PAM:
/*
This is a variant of the Linux-PAM example at
http://www.linux-pam.org/Linux-PAM-html/adg-example.html
modified to use the 'login' PAM service.
That program was contributed by Shane Watts
[modifications by AGM and kukuk]
Save as ex_login.c, compile using (for Linux-PAM):
gcc -Wall -Wextra -O2 ex_login.c -lpam -lpam_misc -o ex_login
or (for OpenPAM):
gcc -DOPENPAM -Wall -Wextra -O2 ex_login.c -lpam -o ex_login
and run
./ex_login username
to authenticate the specified user.
*/
#include <stdlib.h>
#include <security/pam_appl.h>
#ifdef OPENPAM
#include <security/openpam.h>
#define USE_CONV_FUNC openpam_ttyconv
#else
#include <security/pam_misc.h>
#define USE_CONV_FUNC misc_conv
#endif
#include <stdio.h>
static struct pam_conv conv = {
USE_CONV_FUNC,
NULL
};
int main(int argc, char *argv[])
{
const char *arg0 = (argc > 0 && argv && argv[0] && argv[0][0] != '\0') ? argv[0] : "(this)";
pam_handle_t *pamh = NULL;
int retval;
const char *user;
if (argc != 2) {
fprintf(stderr, "\nUsage: %s USERNAME\n\n", arg0);
exit(EXIT_FAILURE);
}
user = argv[1];
retval = pam_start("login", user, &conv, &pamh);
if (retval == PAM_SUCCESS)
retval = pam_authenticate(pamh, 0); /* is user really user? */
if (retval == PAM_SUCCESS)
retval = pam_acct_mgmt(pamh, 0); /* permitted access? */
/* This is where we have been authorized or not. */
if (retval == PAM_SUCCESS) {
fprintf(stdout, "Authenticated\n");
} else {
fprintf(stdout, "Not Authenticated\n");
}
if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
pamh = NULL;
fprintf(stderr, "%s: failed to release authenticator\n", arg0);
exit(EXIT_FAILURE);
}
return ( retval == PAM_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE );
}

Getting undefined reference to misc_conv using Debian libpam0g-dev

Code:
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <stdio.h>
static 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) {
user = argv[1];
}
if(argc > 2) {
fprintf(stderr, "Usage: check_user [username]\n");
exit(1);
}
retval = pam_start("check_user", user, &conv, &pamh);
if (retval == PAM_SUCCESS)
retval = pam_authenticate(pamh, 0); /* is user really user? */
if (retval == PAM_SUCCESS)
retval = pam_acct_mgmt(pamh, 0); /* permitted access? */
/* This is where we have been authorized or not. */
if (retval == PAM_SUCCESS) {
fprintf(stdout, "Authenticated\n");
} else {
fprintf(stdout, "Not Authenticated\n");
}
if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
pamh = NULL;
fprintf(stderr, "check_user: failed to release authenticator\n");
exit(1);
}
return ( retval == PAM_SUCCESS ? 0:1 ); /* indicate success */
}
Two libraries I added:
libpam0g-dev
libpam0g
In /usr/include/security/ I have:
_pam_compat.h
_pam_macros.h
_pam_types.h
pam_appl.h
pam_client.h
pam_ext.h
pam_filter.h
pam_misc.h
pam_modules.h
pam_modutil.h
I compile with: gcc -o check_user -lpam check_user.c
And I get:
/usr/bin/ld: /tmp/cc9ldItB.o:(.data.rel+0x0): undefined reference to `misc_conv'
collect2: error: ld returned 1 exit status
So why do I get undefined reference to "misc_conv' when the libpam0g-dev was added?
You should add the -lpam_misc option to the command:
gcc -o check_user -lpam -lpam_misc check_user.c

Creating a simple shell in C causes linking error

I am creating a simple shell in C that can execute commands, do stdout redirects and piping. So far I got only the redirecting part done but for some reason when i try to compile collect2 throws an error.
The util.c file that I am including:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<signal.h>
#include<errno.h>
#include"util.h"
void setSigHandler(){
void (*oldHandler)();
oldHandler = signal(SIGINT, SIG_IGN);
signal(SIGTERM, oldHandler);
}
void prompt(){
char* user = getlogin();
printf("[%s]-->$", user);
}
void getNextCommand(){
errno = 0;
cmd = malloc(sizeof *cmd);
if(cmd == NULL){
char* error = strerror(errno);
printf("malloc:%s\n", error);
exit(EXIT_FAILURE);
}
fgets(cmd->payload, sizeof(cmd->payload), stdin);
if(cmd->payload[strlen(cmd->payload) - 1] == '\n'){
cmd->payload[strlen(cmd->payload) - 1] = '\0';
}
}
void parseCommandString(){
cmd->payloadArgc = 0;
char* buffer = strtok(cmd->payload, " ");
while(buffer != NULL){
cmd->payloadArgv[cmd->payloadArgc] = buffer;
if(!strcmp(cmd->payloadArgv[cmd->payloadArgc], ">")){
cmd->payloadArgv[cmd->payloadArgc] = NULL;
fileName = strtok(NULL, " ");
break;
}
if(!strcmp(cmd->payloadArgv[cmd->payloadArgc], "|")){
cmd->payloadArgv[cmd->payloadArgc] = NULL;
pCount++;
break;
}
buffer = strtok(NULL, " ");
cmd->payloadArgc++;
}
}
And my main file :
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<errno.h>
#include<signal.h>
#include<sys/file.h>
#include<fcntl.h>
#include"util.h"
int execCommand();
int main(){
setSigHandler();
while(1){
prompt();
getNextCommand();
//pdsh exits on "close"
if(!strcmp(cmd->payloadArgv[0], "close")) break;
parseCommandString();
}
return 0;
}
int execCommand()
{
errno = 0;
int newFd;
// Fork process
pid_t pid = fork();
// Error
if (pid == -1) {
char* error = strerror(errno);
printf("fork: %s\n", error);
return -1;
}
// Child process
else if (pid == 0) {
if(fileName != NULL){
newFd = open(fileName, O_WRONLY | O_CREAT | O_TRUNC, 0755);
if(newFd == -1){
char* error = strerror(errno);
printf("open: %s\n", error);
return -2;
}
dup2(newFd, STDOUT_FILENO);
close(newFd);
}
// Execute command
execvp(cmd->payloadArgv[0], cmd->payloadArgv);
// Error occurred
char* error = strerror(errno);
printf("shell: %s: %s\n", cmd->payloadArgv[0], error);
return -2;
}
// Parent process
else {
close(newFd);
fileName = NULL;
// Wait for child process to finish
int childStatus;
waitpid(pid, &childStatus, 0);
return 0;
}
}
And the error from collect2:
/tmp/ccIXS72e.o:(.bss+0x0): multiple definition of `fileName'
/tmp/ccINCcwP.o:(.bss+0x0): first defined here
/tmp/ccIXS72e.o:(.data+0x0): multiple definition of `pCount'
/tmp/ccINCcwP.o:(.data+0x0): first defined here
/tmp/ccIXS72e.o:(.data+0x4): multiple definition of `newDescriptor'
/tmp/ccINCcwP.o:(.data+0x4): first defined here
collect2: error: ld returned 1 exit status
What is causing this?
I know my main.c code is a little ugly sorry for that.
Edit: The util.h as requested:
#ifndef UTIL_H_
#define UTIL_H_
#define TRUE 1
#define FALSE !TRUE
#define STDOUT 0
#define STDIN 1
#define MAX_CMD_LENGHT 500
#define MAX_CMD_ARGS_LENGHT 50
char* fileName = NULL;
int pCount = -1;
int newDescriptor = -1;
Command cmd;
typedef struct commandR* Command;
struct commandR{
char payload[MAX_CMD_LENGHT];
char* payloadArgv[MAX_CMD_ARGS_LENGHT];
int payloadArgc;
};
void setSigHandler();
void prompt();
void getNextCommand();
void parseCommand();
#endif
Edit 2: After a suggestion I have modified my code. Error still goes off.
util.h
#ifndef UTIL_H_
#define UTIL_H_
#define TRUE 1
#define FALSE !TRUE
#define STDOUT 0
#define STDIN 1
#define MAX_CMD_LENGHT 500
#define MAX_CMD_ARGS_LENGHT 50
extern int newDescriptor;
extern char* fileName;
extern int pCount;
typedef struct commandR* Command;
struct commandR{
char payload[MAX_CMD_LENGHT];
char* payloadArgv[MAX_CMD_ARGS_LENGHT];
int payloadArgc;
};
extern Command cmd;
void setSigHandler();
void prompt();
void getNextCommand();
void parseCommand();
#endif
util.c
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>
#include<signal.h>
#include<errno.h>
#include"util.h"
char* fileName = NULL;
int pCount = -1;
int newDescriptor = -1;
Command cmd;
void setSigHandler(){
void (*oldHandler)();
oldHandler = signal(SIGINT, SIG_IGN);
signal(SIGTERM, oldHandler);
}
void prompt(){
char* user = getlogin();
printf("[%s]-->$", user);
}
void getNextCommand(){
errno = 0;
cmd = malloc(sizeof *cmd);
if(cmd == NULL){
char* error = strerror(errno);
printf("malloc:%s\n", error);
exit(EXIT_FAILURE);
}
fgets(cmd->payload, sizeof(cmd->payload), stdin);
if(cmd->payload[strlen(cmd->payload) - 1] == '\n'){
cmd->payload[strlen(cmd->payload) - 1] = '\0';
}
}
void parseCommandString(){
cmd->payloadArgc = 0;
char* buffer = strtok(cmd->payload, " ");
while(buffer != NULL){
cmd->payloadArgv[cmd->payloadArgc] = buffer;
if(!strcmp(cmd->payloadArgv[cmd->payloadArgc], ">")){
cmd->payloadArgv[cmd->payloadArgc] = NULL;
fileName = strtok(NULL, " ");
break;
}
if(!strcmp(cmd->payloadArgv[cmd->payloadArgc], "|")){
cmd->payloadArgv[cmd->payloadArgc] = NULL;
pCount++;
break;
}
buffer = strtok(NULL, " ");
cmd->payloadArgc++;
}
}
The problem is that you have variables defined in the header file. So when you compile each .c file, they both contain a copy of those variables. This causes the linker error of multiple definitions.
What you need to do is declare them in the header file with the extern keyword. That allows the variables to be used without being defined. Then you define them in exactly one .c file.
util.h:
extern char* fileName;
extern int pCount;
extern int newDescriptor;
extern Command cmd;
util.c:
char* fileName = NULL;
int pCount = -1;
int newDescriptor = -1;
Command cmd;
Also note that the variables are initialized where they are defined, not where they are declared.
EDIT:
It looks like the problem is how you're compiling. You need to compile main.c and util.c to object files, then link the resulting object files:
gcc -Wall -Wextra -g -c main.c
gcc -Wall -Wextra -g -c util.c
gcc -Wall -Wextra -g -o main main.o util.o
Also, you need to put the declaration of parseCommandString into util.h, and you need to include sys/types.h and sys/wait.h in main.c for waitpid.

Not sure why I am getting an undefine refence to gss_str_to_oid error

I am using gssapi in C for the first time. I am trying to reconstruct example on Oracle doc http://docs.oracle.com/cd/E19683-01/816-1331/sampleprogs-1/index.html.
In my .c file I call gss_str_to_oid(&min_stat, &tok, oid); and get an undefined reference error. I included #include "gssapi.h" at the top of my .c file. In gssapi.h there is a function call
OM_uint32 KRB5_CALLCONV
gss_str_to_oid(
OM_uint32 *, /* minor_status */
gss_buffer_t, /* oid_str */
gss_OID *);
So what am I doing wrong? I thought that if you included #include "gssapi.h" it would give me access to function in gssapi. Both files are in my src folder. So what am I doing wrong. I am using eclipse and from what in my makefile under targets it says all: GSS-API.
I am including most of my code below.
main
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <error.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "gssapi.h"
#include "gssapi_ext.h"
#include "gss-misc.h"
/* global mech oid needed by display status, and acquire cred */
FILE *display_file;
gss_OID g_mechOid = GSS_C_NULL_OID;
void usage()
{
fprintf(stderr, "Usage: gss-client [-port port] [-d]"
" [-mech mechOid] host service msg\n");
exit(1);
}
static void parse_oid(char *mechanism, gss_OID *oid)
{
char *mechstr = 0, *cp;
gss_buffer_desc tok;
OM_uint32 maj_stat, min_stat;
if (isdigit(mechanism[0])) {
mechstr = malloc(strlen(mechanism)+5);
if (!mechstr) {
printf("Couldn't allocate mechanism scratch!\n");
return;
}
sprintf(mechstr, "{ %s }", mechanism);
for (cp = mechstr; *cp; cp++)
if (*cp == '.')
*cp = ' ';
tok.value = mechstr;
} else
tok.value = mechanism;
tok.length = strlen(tok.value);
maj_stat = gss_str_to_oid(&min_stat, &tok, oid);
if (maj_stat != GSS_S_COMPLETE) {
// display_status("str_to_oid", maj_stat, min_stat);
return;
}
if (mechstr)
free(mechstr);
}
int main(argc, argv)
int argc;
char **argv;
{
/* char *service_name, *hostname, *msg; */
char *msg;
char service_name[128];
char hostname[128];
char *mechanism = 0;
u_short port = 4444;
int use_file = 0;
OM_uint32 deleg_flag = 0, min_stat;
display_file = stdout;
/* Parse arguments. */
argc--; argv++;
while (argc) {
if (strcmp(*argv, "-port") == 0) {
argc--; argv++;
if (!argc) usage();
port = atoi(*argv);
} else if (strcmp(*argv, "-mech") == 0) {
argc--; argv++;
if (!argc) usage();
mechanism = *argv;
} else if (strcmp(*argv, "-d") == 0) {
deleg_flag = GSS_C_DELEG_FLAG;
} else if (strcmp(*argv, "-f") == 0) {
use_file = 1;
} else
break;
argc--; argv++;
}
if (argc != 3)
usage();
if (argc > 1) {
strcpy(hostname, argv[0]);
} else if (gethostname(hostname, sizeof(hostname)) == -1) {
perror("gethostname");
exit(1);
}
if (argc > 2) {
strcpy(service_name, argv[1]);
strcat(service_name, "#");
strcat(service_name, hostname);
}
msg = argv[2];
if (mechanism)
parse_oid(mechanism, &g_mechOid);
/* if (call_server(hostname, port, g_mechOid, service_name,
deleg_flag, msg, use_file) < 0)
exit(1);*/
/*
if (g_mechOid != GSS_C_NULL_OID)
(void) gss_release_oid(&min_stat, &gmechOid);
*/
return 0;
}
gssapi.h
/* New for V2 */
OM_uint32 KRB5_CALLCONV
gss_str_to_oid(
OM_uint32 *, /* minor_status */
gss_buffer_t, /* oid_str */
gss_OID *);
You just can't include the header you have to link the library either dynamically or statically. Is there some dll, lib, so, etc you need to add to your project? Without makefile or your project setup been shown in your question; I think you will not receive a very clear answer. Just including header file isn't enough, the undefined is not a compilation error but a linker error, which means its missing a reference because you are not linking the library to your program.
The documentation for GSSAPI in C and C++ in not the greatest. Turns out you need to download gssapi. Here is the link http://www.gnu.org/software/gss/manual/gss.html.
It is under download and install
So, I faced same problem.
I found out that you need to add some .so files to your project.
Just in case check that your system has libkrb5-dev packet (most likely it is already installed if you have gssapi.h).
Required files are stored in folder "/usr/lib/x86_64-linux-gnu/" (debian in my case):
I added libkdb5.so and libgssapi_krb5.so to QT .pro file and all works fine:
LIBS += -lkdb5
LIBS += -lgssapi_krb5
If you need to find that files .so use folloing commands:
apt-file update
dpkg -L libkrb5-dev

Issue loading BMP image using SDL_image

I am new to SDL_image and I am trying to use it in a C file to load a BMP image.
To that end, I have written the following code:
#include "SDL/SDL.h"
#include "SDL_image.h"
SDL_RWops *rwop;
rwop = SDL_RWFromFile("sample.bmp", "rb");
However, for some reason, although rwop after those lines are executed is not NULL anymore, IMG_isBMP(rwop) is 0.
Any idea what could be wrong?
Perhaps better example. This (might) yield more information and perhaps if BMP is supported:
https://www.libsdl.org/projects/SDL_image/docs/SDL_image_32.html
You could also try using IMG_LoadBMP_RW as per example here:
https://www.libsdl.org/projects/SDL_image/docs/SDL_image_16.html#SEC16
#include <stdio.h>
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
int main(int argc, char *argv[])
{
const char *fn = "sample.bmp";
SDL_Surface *surf;
if (argc > 1)
fn = argv[1];
if ((surf = SDL_LoadBMP(fn)) == NULL) {
printf("SDL_loadBMP failed: %s\n", SDL_GetError());
SDL_Quit();
return 1;
}
printf("%s is bmp\n", fn);
SDL_FreeSurface(surf);
SDL_Quit();
return 0;
}
Old answer:
Tested and validated:
#include <stdio.h>
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
int main(int argc, char *argv[])
{
const char *fn = "sample.bmp";
int v;
SDL_RWops *rwop;
if (argc > 1)
fn = argv[1];
if ((rwop = SDL_RWFromFile(fn, "rb")) == NULL) {
printf("SDL_RWFromFile failed: %s\n", SDL_GetError());
SDL_Quit();
return 1;
}
v = IMG_isBMP(rwop);
printf("%s is bmp = %d\n", fn, v);
SDL_FreeRW(rwop);
SDL_Quit();
return 0;
}
Compiled with:
gcc -Wall -Wextra -pedantic -o sdl sdl.c `sdl-config --libs` -lSDL_image
Yield for BMP images, e.g.:
$ ./sdltest lena.bmp
lena.bmp is bmp = 1

Resources