]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
Fix pam failure to register Pin following mfa poll
authorDavid Mulder <dmulder@samba.org>
Mon, 9 Sep 2024 19:30:55 +0000 (13:30 -0600)
committerDavid Mulder <dmulder@samba.org>
Wed, 23 Oct 2024 15:39:09 +0000 (15:39 +0000)
Signed-off-by: David Mulder <dmulder@samba.org>
Reviewed-by: Alexander Bokovoy <ab@samba.org>
Autobuild-User(master): David Mulder <dmulder@samba.org>
Autobuild-Date(master): Wed Oct 23 15:39:09 UTC 2024 on atb-devel-224

rust/pam/src/pam/mod.rs

index 5ed73f7aeda77d4e0445175ea14b6c0da687f541..7447ee09a3af74c5e2ededaeb7bda411ac24aaf8 100755 (executable)
@@ -120,7 +120,7 @@ pub struct PamHimmelblau;
 pam_hooks!(PamHimmelblau);
 
 macro_rules! match_sm_auth_client_response {
-    ($expr:expr, $opts:ident, $($pat:pat => $result:expr),*) => {
+    ($expr:expr, $opts:ident, $conv:ident, $req:ident, $authtok:ident, $($pat:pat => $result:expr),*) => {
         match $expr {
             Ok(r) => match r {
                 $($pat => $result),*
@@ -137,6 +137,99 @@ macro_rules! match_sm_auth_client_response {
                         return PamResultCode::PAM_USER_UNKNOWN;
                     }
                 }
+                Response::PamAuthStepResponse(PamAuthResponse::SetupPin {
+                    msg,
+                }) => {
+                    match $conv.send(PAM_TEXT_INFO, &msg) {
+                        Ok(_) => {}
+                        Err(err) => {
+                            if $opts.debug {
+                                println!("Message prompt failed");
+                            }
+                            return err;
+                        }
+                    }
+
+                    let mut pin;
+                    let mut confirm;
+                    loop {
+                        pin = match $conv.send(PAM_PROMPT_ECHO_OFF, "New PIN: ") {
+                            Ok(password) => match password {
+                                Some(cred) => cred,
+                                None => {
+                                    DBG_DEBUG!("no pin");
+                                    return PamResultCode::PAM_CRED_INSUFFICIENT;
+                                }
+                            },
+                            Err(err) => {
+                                DBG_DEBUG!("unable to get pin");
+                                return err;
+                            }
+                        };
+
+                        confirm = match $conv.send(PAM_PROMPT_ECHO_OFF, "Confirm PIN: ") {
+                            Ok(password) => match password {
+                                Some(cred) => cred,
+                                None => {
+                                    DBG_DEBUG!("no confirmation pin");
+                                    return PamResultCode::PAM_CRED_INSUFFICIENT;
+                                }
+                            },
+                            Err(err) => {
+                                DBG_DEBUG!("unable to get confirmation pin");
+                                return err;
+                            }
+                        };
+
+                        if pin == confirm {
+                            break;
+                        } else {
+                            match $conv.send(PAM_TEXT_INFO, "Inputs did not match. Try again.") {
+                                Ok(_) => {}
+                                Err(err) => {
+                                    if $opts.debug {
+                                        println!("Message prompt failed");
+                                    }
+                                    return err;
+                                }
+                            }
+                        }
+                    }
+
+                    // Now setup the request for the next loop.
+                    $req = Request::PamAuthenticateStep(PamAuthRequest::SetupPin {
+                        pin,
+                    });
+                    continue;
+                },
+                Response::PamAuthStepResponse(PamAuthResponse::Pin) => {
+                    let mut consume_authtok = None;
+                    // Swap the authtok out with a None, so it can only be consumed once.
+                    // If it's already been swapped, we are just swapping two null pointers
+                    // here effectively.
+                    std::mem::swap(&mut $authtok, &mut consume_authtok);
+                    let cred = if let Some(cred) = consume_authtok {
+                        cred
+                    } else {
+                        match $conv.send(PAM_PROMPT_ECHO_OFF, "PIN: ") {
+                            Ok(password) => match password {
+                                Some(cred) => cred,
+                                None => {
+                                    DBG_DEBUG!("no pin");
+                                    return PamResultCode::PAM_CRED_INSUFFICIENT;
+                                }
+                            },
+                            Err(err) => {
+                                DBG_DEBUG!("unable to get pin");
+                                return err;
+                            }
+                        }
+                    };
+
+                    // Now setup the request for the next loop.
+                    $req = Request::PamAuthenticateStep(PamAuthRequest::Pin { pin: cred });
+                    continue;
+                }
                 _ => {
                     // unexpected response.
                     DBG_ERR!("PAM_IGNORE, unexpected resolver response: {:?}", r);
@@ -301,7 +394,7 @@ impl PamHooks for PamHimmelblau {
         let mut req = Request::PamAuthenticateInit(account_id);
 
         loop {
-            match_sm_auth_client_response!(stream.send(&req, timeout), opts,
+            match_sm_auth_client_response!(stream.send(&req, timeout), opts, conv, req, authtok,
                 Response::PamAuthStepResponse(PamAuthResponse::Password) => {
                     let mut consume_authtok = None;
                     // Swap the authtok out with a None, so it can only be consumed once.
@@ -383,116 +476,26 @@ impl PamHooks for PamHimmelblau {
                     let _ = conv.send(PAM_PROMPT_ECHO_OFF, "Press enter to continue");
 
                     let mut poll_attempt = 0;
+                    req = Request::PamAuthenticateStep(
+                        PamAuthRequest::MFAPoll { poll_attempt }
+                    );
                     loop {
                         thread::sleep(Duration::from_secs(polling_interval.into()));
-                        req = Request::PamAuthenticateStep(
-                            PamAuthRequest::MFAPoll { poll_attempt }
-                        );
 
                         match_sm_auth_client_response!(
-                            stream.send(&req, timeout), opts,
+                            stream.send(&req, timeout), opts, conv, req, authtok,
                             Response::PamAuthStepResponse(
                                     PamAuthResponse::MFAPollWait,
                             ) => {
                                 // Continue polling if the daemon says to wait
                                 poll_attempt += 1;
+                                req = Request::PamAuthenticateStep(
+                                    PamAuthRequest::MFAPoll { poll_attempt }
+                                );
                                 continue;
                             }
                         );
                     }
-                },
-                Response::PamAuthStepResponse(PamAuthResponse::SetupPin {
-                    msg,
-                }) => {
-                    match conv.send(PAM_TEXT_INFO, &msg) {
-                        Ok(_) => {}
-                        Err(err) => {
-                            if opts.debug {
-                                println!("Message prompt failed");
-                            }
-                            return err;
-                        }
-                    }
-
-                    let mut pin;
-                    let mut confirm;
-                    loop {
-                        pin = match conv.send(PAM_PROMPT_ECHO_OFF, "New PIN: ") {
-                            Ok(password) => match password {
-                                Some(cred) => cred,
-                                None => {
-                                    DBG_DEBUG!("no pin");
-                                    return PamResultCode::PAM_CRED_INSUFFICIENT;
-                                }
-                            },
-                            Err(err) => {
-                                DBG_DEBUG!("unable to get pin");
-                                return err;
-                            }
-                        };
-
-                        confirm = match conv.send(PAM_PROMPT_ECHO_OFF, "Confirm PIN: ") {
-                            Ok(password) => match password {
-                                Some(cred) => cred,
-                                None => {
-                                    DBG_DEBUG!("no confirmation pin");
-                                    return PamResultCode::PAM_CRED_INSUFFICIENT;
-                                }
-                            },
-                            Err(err) => {
-                                DBG_DEBUG!("unable to get confirmation pin");
-                                return err;
-                            }
-                        };
-
-                        if pin == confirm {
-                            break;
-                        } else {
-                            match conv.send(PAM_TEXT_INFO, "Inputs did not match. Try again.") {
-                                Ok(_) => {}
-                                Err(err) => {
-                                    if opts.debug {
-                                        println!("Message prompt failed");
-                                    }
-                                    return err;
-                                }
-                            }
-                        }
-                    }
-
-                    // Now setup the request for the next loop.
-                    req = Request::PamAuthenticateStep(PamAuthRequest::SetupPin {
-                        pin,
-                    });
-                    continue;
-                },
-                Response::PamAuthStepResponse(PamAuthResponse::Pin) => {
-                    let mut consume_authtok = None;
-                    // Swap the authtok out with a None, so it can only be consumed once.
-                    // If it's already been swapped, we are just swapping two null pointers
-                    // here effectively.
-                    std::mem::swap(&mut authtok, &mut consume_authtok);
-                    let cred = if let Some(cred) = consume_authtok {
-                        cred
-                    } else {
-                        match conv.send(PAM_PROMPT_ECHO_OFF, "PIN: ") {
-                            Ok(password) => match password {
-                                Some(cred) => cred,
-                                None => {
-                                    DBG_DEBUG!("no pin");
-                                    return PamResultCode::PAM_CRED_INSUFFICIENT;
-                                }
-                            },
-                            Err(err) => {
-                                DBG_DEBUG!("unable to get pin");
-                                return err;
-                            }
-                        }
-                    };
-
-                    // Now setup the request for the next loop.
-                    req = Request::PamAuthenticateStep(PamAuthRequest::Pin { pin: cred });
-                    continue;
                 }
             );
         } // while true, continue calling PamAuthenticateStep until we get a decision.