blank.c
/* * $Id$ */ /* Andrew Morgan (morgan@parc.power.net) -- a self contained `blank' * application * * I am not very proud of this code. It makes use of a possibly ill- * defined pamh pointer to call pam_strerror() with. The reason that * I was sloppy with this is historical (pam_strerror, prior to 0.59, * did not require a pamh argument) and if this program is used as a * model for anything, I should wish that you will take this error into * account. */ #include <stdio.h> #include <stdlib.h> #include <security/pam_appl.h> #include <security/pam_misc.h> /* ------ some local (static) functions ------- */ static void bail_out(pam_handle_t *pamh, int really, int code, const char *fn) { fprintf(stderr,"==> called %s() got: `%s' ", fn, pam_strerror(pamh, code)); if (really && code) exit (1); } /* ------ some static data objects ------- */ static struct pam_conv conv = { misc_conv, NULL }; /* ------- the application itself -------- */ int main(int argc, char **argv) { pam_handle_t *pamh=NULL; char *username=NULL; int retcode; /* did the user call with a username as an argument ? */ if (argc > 2) { fprintf(stderr,"usage: %s [username] ",argv[0]); } else if (argc == 2) { username = argv[1]; } /* initialize the Linux-PAM library */ retcode = pam_start("blank", username, &conv, &pamh); bail_out(pamh,1,retcode,"pam_start"); /* test the environment stuff */ { #define MAXENV 15 const char *greek[MAXENV] = { "a=alpha", "b=beta", "c=gamma", "d=delta", "e=epsilon", "f=phi", "g=psi", "h=eta", "i=iota", "j=mu", "k=nu", "l=zeta", "h=", "d", "k=xi" }; char **env; int i; for (i=0; i<MAXENV; ++i) { retcode = pam_putenv(pamh,greek[i]); bail_out(pamh,0,retcode,"pam_putenv"); } env = pam_getenvlist(pamh); if (env) env = pam_misc_drop_env(env); else fprintf(stderr,"??? "); fprintf(stderr,"a test: c=[%s], j=[%s] " , pam_getenv(pamh, "c"), pam_getenv(pamh, "j")); } /* to avoid using goto we abuse a loop here */ for (;;) { /* authenticate the user --- `0' here, could have been PAM_SILENT * | PAM_DISALLOW_NULL_AUTHTOK */ retcode = pam_authenticate(pamh, 0); bail_out(pamh,0,retcode,"pam_authenticate"); /* has the user proved themself valid? */ if (retcode != PAM_SUCCESS) { fprintf(stderr,"%s: invalid request ",argv[0]); break; } /* the user is valid, but should they have access at this time? */ retcode = pam_acct_mgmt(pamh, 0); /* `0' could be as above */ bail_out(pamh,0,retcode,"pam_acct_mgmt"); if (retcode == PAM_NEW_AUTHTOK_REQD) { fprintf(stderr,"Application must request new password... "); retcode = pam_chauthtok(pamh,PAM_CHANGE_EXPIRED_AUTHTOK); bail_out(pamh,0,retcode,"pam_chauthtok"); } if (retcode != PAM_SUCCESS) { fprintf(stderr,"%s: invalid request ",argv[0]); break; } /* `0' could be as above */ retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED); bail_out(pamh,0,retcode,"pam_setcred1"); if (retcode != PAM_SUCCESS) { fprintf(stderr,"%s: problem setting user credentials " ,argv[0]); break; } /* open a session for the user --- `0' could be PAM_SILENT */ retcode = pam_open_session(pamh,0); bail_out(pamh,0,retcode,"pam_open_session"); if (retcode != PAM_SUCCESS) { fprintf(stderr,"%s: problem opening a session ",argv[0]); break; } fprintf(stderr,"The user has been authenticated and `logged in' "); /* close a session for the user --- `0' could be PAM_SILENT * it is possible that this pam_close_call is in another program.. */ retcode = pam_close_session(pamh,0); bail_out(pamh,0,retcode,"pam_close_session"); if (retcode != PAM_SUCCESS) { fprintf(stderr,"%s: problem closing a session ",argv[0]); break; } retcode = pam_setcred(pamh, PAM_DELETE_CRED); bail_out(pamh,0,retcode,"pam_setcred2"); break; /* don't go on for ever! */ } /* close the Linux-PAM library */ retcode = pam_end(pamh, PAM_SUCCESS); pamh = NULL; bail_out(pamh,1,retcode,"pam_end"); exit(0); }
check_user.c
/* $Id$ This program was contributed by Shane Watts <shane@icarus.bofh.asn.au> slight modifications by AGM. You need to add the following (or equivalent) to the /etc/pam.conf file. # check authorization check auth required pam_unix_auth.so check account required pam_unix_acct.so */ #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] "); exit(1); } retval = pam_start("check", 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 "); } else { fprintf(stdout, "Not Authenticated "); } if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */ pamh = NULL; fprintf(stderr, "check_user: failed to release authenticator "); exit(1); } return ( retval == PAM_SUCCESS ? 0:1 ); /* indicate success */ }
vpass.c
#include "config.h" #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <pwd.h> #include <sys/types.h> #include <security/pam_appl.h> static int test_conv (int num_msg UNUSED, const struct pam_message **msgm UNUSED, struct pam_response **response UNUSED, void *appdata_ptr UNUSED) { return 0; } static struct pam_conv conv = { test_conv, NULL }; int main(void) { char *user; pam_handle_t *pamh; struct passwd *pw; uid_t uid; int res; uid = geteuid(); pw = getpwuid(uid); if (pw) { user = pw->pw_name; } else { fprintf(stderr, "Invalid userid: %lu ", (unsigned long) uid); exit(1); } pam_start("vpass", user, &conv, &pamh); pam_set_item(pamh, PAM_TTY, "/dev/tty"); if ((res = pam_authenticate(pamh, 0)) != PAM_SUCCESS) { fprintf(stderr, "Oops: %s ", pam_strerror(pamh, res)); exit(1); } pam_end(pamh, res); exit(0); }
xsh.c
/* Andrew Morgan (morgan@kernel.org) -- an example application * that invokes a shell, based on blank.c */ #include "config.h" #include <stdio.h> #include <stdlib.h> #include <security/pam_appl.h> #include <security/pam_misc.h> #include <pwd.h> #include <sys/types.h> #include <unistd.h> /* ------ some local (static) functions ------- */ static void bail_out(pam_handle_t *pamh,int really, int code, const char *fn) { fprintf(stderr,"==> called %s() got: `%s' ", fn, pam_strerror(pamh,code)); if (really && code) exit (1); } /* ------ some static data objects ------- */ static struct pam_conv conv = { misc_conv, NULL }; /* ------- the application itself -------- */ int main(int argc, char **argv) { pam_handle_t *pamh=NULL; const void *username=NULL; const char *service="xsh"; int retcode; /* did the user call with a username as an argument ? * did they also */ if (argc > 3) { fprintf(stderr,"usage: %s [username [service-name]] ",argv[0]); } if ((argc >= 2) && (argv[1][0] != '-')) { username = argv[1]; } if (argc == 3) { service = argv[2]; } /* initialize the Linux-PAM library */ retcode = pam_start(service, username, &conv, &pamh); bail_out(pamh,1,retcode,"pam_start"); /* fill in the RUSER and RHOST etc. fields */ { char buffer[100]; struct passwd *pw; const char *tty; pw = getpwuid(getuid()); if (pw != NULL) { retcode = pam_set_item(pamh, PAM_RUSER, pw->pw_name); bail_out(pamh,1,retcode,"pam_set_item(PAM_RUSER)"); } retcode = gethostname(buffer, sizeof(buffer)-1); if (retcode) { perror("failed to look up hostname"); retcode = pam_end(pamh, PAM_ABORT); bail_out(pamh,1,retcode,"pam_end"); } retcode = pam_set_item(pamh, PAM_RHOST, buffer); bail_out(pamh,1,retcode,"pam_set_item(PAM_RHOST)"); tty = ttyname(fileno(stdin)); if (tty) { retcode = pam_set_item(pamh, PAM_TTY, tty); bail_out(pamh,1,retcode,"pam_set_item(PAM_RHOST)"); } } /* to avoid using goto we abuse a loop here */ for (;;) { /* authenticate the user --- `0' here, could have been PAM_SILENT * | PAM_DISALLOW_NULL_AUTHTOK */ retcode = pam_authenticate(pamh, 0); bail_out(pamh,0,retcode,"pam_authenticate"); /* has the user proved themself valid? */ if (retcode != PAM_SUCCESS) { fprintf(stderr,"%s: invalid request ",argv[0]); break; } /* the user is valid, but should they have access at this time? */ retcode = pam_acct_mgmt(pamh, 0); /* `0' could be as above */ bail_out(pamh,0,retcode,"pam_acct_mgmt"); if (retcode == PAM_NEW_AUTHTOK_REQD) { fprintf(stderr,"Application must request new password... "); retcode = pam_chauthtok(pamh,PAM_CHANGE_EXPIRED_AUTHTOK); bail_out(pamh,0,retcode,"pam_chauthtok"); } if (retcode != PAM_SUCCESS) { fprintf(stderr,"%s: invalid request ",argv[0]); break; } /* `0' could be as above */ retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED); bail_out(pamh,0,retcode,"pam_setcred"); if (retcode != PAM_SUCCESS) { fprintf(stderr,"%s: problem setting user credentials " ,argv[0]); break; } /* open a session for the user --- `0' could be PAM_SILENT */ retcode = pam_open_session(pamh,0); bail_out(pamh,0,retcode,"pam_open_session"); if (retcode != PAM_SUCCESS) { fprintf(stderr,"%s: problem opening a session ",argv[0]); break; } pam_get_item(pamh, PAM_USER, &username); fprintf(stderr, "The user [%s] has been authenticated and `logged in' ", (const char *)username); /* this is always a really bad thing for security! */ retcode = system("/bin/sh"); /* close a session for the user --- `0' could be PAM_SILENT * it is possible that this pam_close_call is in another program.. */ retcode = pam_close_session(pamh,0); bail_out(pamh,0,retcode,"pam_close_session"); if (retcode != PAM_SUCCESS) { fprintf(stderr,"%s: problem closing a session ",argv[0]); break; } /* `0' could be as above */ retcode = pam_setcred(pamh, PAM_DELETE_CRED); bail_out(pamh,0,retcode,"pam_setcred"); if (retcode != PAM_SUCCESS) { fprintf(stderr,"%s: problem deleting user credentials " ,argv[0]); break; } break; /* don't go on for ever! */ } /* close the Linux-PAM library */ retcode = pam_end(pamh, PAM_SUCCESS); pamh = NULL; bail_out(pamh,1,retcode,"pam_end"); return (0); }