Skip to content

Commit

Permalink
Merge pull request #7 from Telmate/pam_sessions_anthony
Browse files Browse the repository at this point in the history
Call pam_open_session only after VPN fully up
  • Loading branch information
avis authored Jun 15, 2020
2 parents 8de4695 + 4c4ca6a commit 9fc620a
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 28 deletions.
15 changes: 15 additions & 0 deletions programs/pluto/ikev1_quick.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@
#include "alg_info.h"
#include "ip_address.h"

#include "pam_conv.h" /* needs struct xauth */

#include <blapit.h>

/* accept_PFS_KE
Expand Down Expand Up @@ -1987,5 +1989,18 @@ stf_status quick_inI2(struct state *st, struct msg_digest *md)
}
}

/*
* Tell the xauth thread it's finally time to start the session for
* e.g., billing. We need to find the phase1 state, though, since
* that's where the xauth is.
*/
struct state *p1st = state_with_serialno(st->st_clonedfrom);
if (!p1st || !p1st->st_xauth) {
delete_ipsec_sa(st);
return STF_FAIL;

}
atomic_flag_clear(&p1st->st_xauth->vpn_still_starting);

return STF_OK;
}
81 changes: 58 additions & 23 deletions programs/pluto/pam_conv.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <string.h>
#include <stdlib.h>
#include <security/pam_appl.h> /* needed for pam_handle_t */
#include <spawn.h>

#include "defs.h"
#include "lswlog.h"
Expand All @@ -41,9 +42,10 @@
#include "log.h"
#include "state.h"

extern char **environ; /* because apparently not _GNU_SOURCE */

static char *pam_state_enum[] = {
"PAM_AUTH","PAM_SESSION_START", "PAM_SESSION_END", "PAM_TERM", "PAM_STATE_UNKNOWN", "PAM_DO_NOTHING"
"PAM_AUTH", "PAM_CALLBACK", "PAM_SESSION_START", "PAM_SESSION_END", "PAM_TERM", "PAM_STATE_UNKNOWN", "PAM_DO_NOTHING"
};

static char *pam_result_state_enum[] = { "PAM_AUTH_SUCCESS", "PAM_AUTH_FAIL", "PAM_SESSION_START_SUCCESS", "PAM_SESSION_START_FAIL", "PAM_SESSION_END_SUCCESS", "PAM_SESSION_END_FAIL", "PAM_TERM_SUCCESS", "PAM_TERM_FAIL", "PAM_RESULT_UNKNOWN"
Expand Down Expand Up @@ -223,7 +225,7 @@ void *pam_thread(void *parg)
if (retval == PAM_SUCCESS) {
/* do promotion to session start */
ptr_xauth->ptarg.pam_state = PAM_AUTH_SUCCESS;
ptr_xauth->ptarg.pam_do_state = PAM_SESSION_START;
ptr_xauth->ptarg.pam_do_state = PAM_CALLBACK;

break; // break out of pam_acct_mgmt loop

Expand Down Expand Up @@ -255,41 +257,74 @@ void *pam_thread(void *parg)
}

}
} else if(ptr_xauth->ptarg.pam_do_state == PAM_CALLBACK) {
log_pam_step((struct pam_thread_arg *)&ptr_xauth->ptarg, "making xauth callback");

} else if(ptr_xauth->ptarg.pam_do_state == PAM_SESSION_START) {
struct state *st = state_with_serialno(ptr_xauth->serialno);
if(st != NULL) {
so_serial_t old_state = push_cur_state(st);

for (int i = 0; i < 5; i++) {
libreswan_log("XAUTH: #%lu: completed for user '%s' (waiting for VPN up for session_start)",
ptr_xauth->ptarg.st_serialno, ptr_xauth->ptarg.name);

ptr_xauth->callback(st, ptr_xauth->ptarg.name, TRUE);
pop_cur_state(old_state);
}
ptr_xauth->ptarg.pam_do_state = PAM_SESSION_START;
} else if(ptr_xauth->ptarg.pam_do_state == PAM_SESSION_START) {
if (atomic_flag_test_and_set(&ptr_xauth->vpn_still_starting)) {
log_pam_step(&ptr_xauth->ptarg, "waiting for VPN up");
} else {
what = "pam_open_session";
retval = pam_open_session(pamh, PAM_SILENT);
log_pam_step((struct pam_thread_arg *)&ptr_xauth->ptarg, what);
if (retval == PAM_SUCCESS) {

bool success = TRUE;
struct state *st = state_with_serialno(ptr_xauth->serialno);
//passert(st != NULL);
if(st != NULL) {
so_serial_t old_state = push_cur_state(st);

libreswan_log("XAUTH: #%lu: completed for user '%s' with status %s ::: pam_open_session",
ptr_xauth->ptarg.st_serialno, ptr_xauth->ptarg.name,
success ? "SUCCESSS" : "FAILURE");

ptr_xauth->callback(st, ptr_xauth->ptarg.name, success);
pop_cur_state(old_state);
}
struct state *st = state_with_serialno(ptr_xauth->serialno);
if (!st) {
/* should never happen, just log if it does */
libreswan_log("XAUTH: #%lu: INTERNAL ERROR Could not find SA state object for user '%s' ::: pam_open_session",
ptr_xauth->ptarg.st_serialno, ptr_xauth->ptarg.name);
}
libreswan_log("XAUTH: #%lu: completed for user '%s' with status %s ::: pam_open_session",
ptr_xauth->ptarg.st_serialno, ptr_xauth->ptarg.name,
(retval == PAM_SUCCESS ? "SUCCESS" : "FAILURE"));

if (retval == PAM_SUCCESS) {
ptr_xauth->ptarg.pam_state = PAM_SESSION_START_SUCCESS;
ptr_xauth->ptarg.pam_do_state = PAM_DO_NOTHING;

break;
} else {
ptr_xauth->ptarg.pam_state = PAM_SESSION_START_FAIL;
ptr_xauth->ptarg.pam_do_state = PAM_TERM;
}
}
/* Failed pam_open_session */

/*
* Ideally, sending the message would be a library, but it's
* not... so only way to re-use that code is to just call ipsec
* whack. Hopefully posix_spawn avoids the pthread/fork issues.
*/
pid_t child;
int res;
char buf[32]; /* 2^64-1 needs 21 */
res = snprintf(buf, sizeof(buf), "%lu", ptr_xauth->serialno);
if (res < 0 || (unsigned int)res >= sizeof(buf)) {
libreswan_log("XAUTH: #%lu: snprintf failure while downing VPN for user '%s'",
ptr_xauth->ptarg.st_serialno, ptr_xauth->ptarg.name);
continue;
}
char *args[] = {
"ipsec", "whack", "--deletestate", buf, NULL
};
int err = posix_spawnp(&child, "ipsec", NULL, NULL, args, environ);
if (err) {
libreswan_log("XAUTH: #%lu: posix_spawnp failure while downing VPN for user '%s'",
ptr_xauth->ptarg.st_serialno, ptr_xauth->ptarg.name);
continue;
}

libreswan_log("XAUTH: #%lu: sent VPN down command for user '%s'",
ptr_xauth->ptarg.st_serialno, ptr_xauth->ptarg.name);
}
/* Failed pam_open_session */
}
} else if(ptr_xauth->ptarg.pam_do_state == PAM_SESSION_END) {

for (int i = 0; i < 5; i++) {
Expand Down
13 changes: 8 additions & 5 deletions programs/pluto/pam_conv.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

//#include "xauth.h"
#include "constants.h"
#include <stdatomic.h>
struct state;

typedef void xauth_callback_t(
Expand All @@ -30,11 +31,12 @@ struct app_pam_data { const char* password; };

enum pam_state_t {
PAM_AUTH = 0,
PAM_SESSION_START = 1,
PAM_SESSION_END = 2,
PAM_TERM = 3,
PAM_STATE_UNKNOWN = 4,
PAM_DO_NOTHING = 5
PAM_CALLBACK = 1,
PAM_SESSION_START = 2,
PAM_SESSION_END = 3,
PAM_TERM = 4,
PAM_STATE_UNKNOWN = 5,
PAM_DO_NOTHING = 6

};

Expand Down Expand Up @@ -75,6 +77,7 @@ struct xauth {
xauth_callback_t *callback;
bool abort;
pid_t child;
atomic_flag vpn_still_starting;
};

extern bool do_pam_authentication(struct pam_thread_arg *arg);
Expand Down
1 change: 1 addition & 0 deletions programs/pluto/xauth.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ void xauth_start_pam_thread(struct state *st,

xauth->callback = callback;
xauth->serialno = serialno;
atomic_flag_test_and_set(&xauth->vpn_still_starting);
gettimeofday(&xauth->tv0, NULL);

/* fill in pam_thread_arg with info for the child process */
Expand Down

0 comments on commit 9fc620a

Please sign in to comment.