diff --git a/programs/pluto/ikev1_quick.c b/programs/pluto/ikev1_quick.c index 7bb4a278d54..e043c027347 100644 --- a/programs/pluto/ikev1_quick.c +++ b/programs/pluto/ikev1_quick.c @@ -83,6 +83,8 @@ #include "alg_info.h" #include "ip_address.h" +#include "pam_conv.h" /* needs struct xauth */ + #include /* accept_PFS_KE @@ -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; } diff --git a/programs/pluto/pam_conv.c b/programs/pluto/pam_conv.c index 1108e2c2a4c..5900c3caa39 100644 --- a/programs/pluto/pam_conv.c +++ b/programs/pluto/pam_conv.c @@ -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" @@ -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 @@ -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++) { diff --git a/programs/pluto/pam_conv.h b/programs/pluto/pam_conv.h index 7ca240b2a10..452bd5d59f2 100644 --- a/programs/pluto/pam_conv.h +++ b/programs/pluto/pam_conv.h @@ -19,6 +19,7 @@ //#include "xauth.h" #include "constants.h" +#include struct state; typedef void xauth_callback_t( @@ -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 }; @@ -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); diff --git a/programs/pluto/xauth.c b/programs/pluto/xauth.c index 235fd81bf85..24dbd3dcb28 100644 --- a/programs/pluto/xauth.c +++ b/programs/pluto/xauth.c @@ -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 */