view src/memory.rs @ 69:8f3ae0c7ab92

Rework conversation data types and make safe wrappers. This removes the old `Conversation` type and reworks the FFI types used for PAM conversations. This creates safe `TestResponse` and `BinaryResponse` structures in `conv`, providing a safe way to pass response messages to PAM Conversations. The internals of these types are allocated on the C heap, as required by PAM. We also remove the Conversation struct, which was specific to the real PAM implementation so that we can introduce a better abstraction. Also splits a new `PamApplicationHandle` trait from `PamHandle`, for the parts of a PAM handle that are specific to the application side of a PAM transaction.
author Paul Fisher <paul@pfish.zone>
date Sun, 01 Jun 2025 01:15:04 -0400
parents bbe84835d6db
children
line wrap: on
line source

//! Utility functions for dealing with memory copying and stuff.

use crate::constants::{ErrorCode, Result};
use libc::c_char;
use std::ffi::{CStr, CString};

/// Safely converts a `&str` option to a `CString` option.
pub fn option_cstr(prompt: Option<&str>) -> Result<Option<CString>> {
    prompt
        .map(CString::new)
        .transpose()
        .map_err(|_| ErrorCode::ConversationError)
}

/// Gets the pointer to the given CString, or a null pointer if absent.
pub fn prompt_ptr(prompt: Option<&CString>) -> *const c_char {
    match prompt {
        Some(c_str) => c_str.as_ptr(),
        None => std::ptr::null(),
    }
}

/// Creates an owned copy of a string that is returned from a
/// <code>pam_get_<var>whatever</var></code> function.
pub fn copy_pam_string(result_ptr: *const c_char) -> Result<String> {
    // We really shouldn't get a null pointer back here, but if we do, return nothing.
    if result_ptr.is_null() {
        return Ok(String::new());
    }
    let bytes = unsafe { CStr::from_ptr(result_ptr) };
    bytes
        .to_str()
        .map(String::from)
        .map_err(|_| ErrorCode::ConversationError)
}