@@ -1282,10 +1282,14 @@ int krb5_auth_recv(struct tevent_req *req, int *pam_status, int *dp_err)
12821282}
12831283
12841284struct krb5_pam_handler_state {
1285+ struct tevent_context * ev ;
1286+ struct be_ctx * be_ctx ;
12851287 struct pam_data * pd ;
1288+ struct krb5_ctx * krb5_ctx ;
12861289};
12871290
12881291static void krb5_pam_handler_auth_done (struct tevent_req * subreq );
1292+ static void krb5_pam_handler_auth_retry_done (struct tevent_req * subreq );
12891293static void krb5_pam_handler_access_done (struct tevent_req * subreq );
12901294
12911295struct tevent_req *
@@ -1305,7 +1309,10 @@ krb5_pam_handler_send(TALLOC_CTX *mem_ctx,
13051309 return NULL ;
13061310 }
13071311
1312+ state -> ev = params -> ev ;
1313+ state -> be_ctx = params -> be_ctx ;
13081314 state -> pd = pd ;
1315+ state -> krb5_ctx = krb5_ctx ;
13091316
13101317 switch (pd -> cmd ) {
13111318 case SSS_PAM_AUTHENTICATE :
@@ -1372,6 +1379,49 @@ static void krb5_pam_handler_auth_done(struct tevent_req *subreq)
13721379 state -> pd -> pam_status = PAM_SYSTEM_ERR ;
13731380 }
13741381
1382+ if (state -> pd -> cmd == SSS_PAM_CHAUTHTOK_PRELIM
1383+ && state -> pd -> pam_status == PAM_TRY_AGAIN ) {
1384+ /* Reset this to fork a new krb5_child in handle_child_send() */
1385+ state -> pd -> child_pid = 0 ;
1386+ subreq = krb5_auth_queue_send (state , state -> ev , state -> be_ctx , state -> pd ,
1387+ state -> krb5_ctx );
1388+ if (subreq == NULL ) {
1389+ goto done ;
1390+ }
1391+
1392+ tevent_req_set_callback (subreq , krb5_pam_handler_auth_retry_done , req );
1393+ return ;
1394+ }
1395+
1396+ /* PAM_CRED_ERR is used to indicate to the IPA provider that trying
1397+ * password migration would make sense. From this point on it isn't
1398+ * necessary to keep this status, so it can be translated to PAM_AUTH_ERR.
1399+ */
1400+ if (state -> pd -> pam_status == PAM_CRED_ERR ) {
1401+ state -> pd -> pam_status = PAM_AUTH_ERR ;
1402+ }
1403+
1404+ done :
1405+ /* TODO For backward compatibility we always return EOK to DP now. */
1406+ tevent_req_done (req );
1407+ }
1408+
1409+ static void krb5_pam_handler_auth_retry_done (struct tevent_req * subreq )
1410+ {
1411+ struct krb5_pam_handler_state * state ;
1412+ struct tevent_req * req ;
1413+ errno_t ret ;
1414+
1415+ req = tevent_req_callback_data (subreq , struct tevent_req );
1416+ state = tevent_req_data (req , struct krb5_pam_handler_state );
1417+
1418+ ret = krb5_auth_queue_recv (subreq , & state -> pd -> pam_status , NULL );
1419+ talloc_free (subreq );
1420+ if (ret != EOK ) {
1421+ DEBUG (SSSDBG_OP_FAILURE , "krb5_auth_recv request failed.\n" );
1422+ state -> pd -> pam_status = PAM_SYSTEM_ERR ;
1423+ }
1424+
13751425 /* PAM_CRED_ERR is used to indicate to the IPA provider that trying
13761426 * password migration would make sense. From this point on it isn't
13771427 * necessary to keep this status, so it can be translated to PAM_AUTH_ERR.
0 commit comments