Skip to content

Commit

Permalink
Move pam session start to after VPN up
Browse files Browse the repository at this point in the history
PAM session start needs only if, and only once, the VPN is fully up.
Want to only have started sessions when it has fully worked.

Add another state to the pam_conv sort-of state machine for makeing the
xauth success callback, before starting to wait for VPN up to start the
PAM session.

Remember that st_xauth is on the phase1 state, not phase2.

Next commit will handle downing the VPN if pam session start fails.
  • Loading branch information
derobert committed Jun 11, 2020
1 parent 8de4695 commit 9947bd3
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 34 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;
}
69 changes: 40 additions & 29 deletions programs/pluto/pam_conv.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@


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 +223,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 +255,52 @@ 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) {

for (int i = 0; i < 5; i++) {
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) {
struct state *st = state_with_serialno(ptr_xauth->serialno);
if(st != NULL) {
so_serial_t old_state = push_cur_state(st);

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' (waiting for VPN up for session_start)",
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,
success ? "SUCCESSS" : "FAILURE");
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 {
for (int i = 0; i < 5; i++) {
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) {
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);
}
}

ptr_xauth->ptarg.pam_state = PAM_SESSION_START_SUCCESS;
ptr_xauth->ptarg.pam_do_state = PAM_DO_NOTHING;
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;
break;
} else {
ptr_xauth->ptarg.pam_state = PAM_SESSION_START_FAIL;
ptr_xauth->ptarg.pam_do_state = PAM_TERM;
/* FIXME: Need to kill the VPN here */
}
}
/* Failed pam_open_session */
}
/* 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 9947bd3

Please sign in to comment.