diff --git a/Cargo.lock b/Cargo.lock index 648d490..6c85149 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -410,7 +410,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a969e13a7589e9e3e4207e153bae624ade2b5622fb4684a4923b23ec3d57719" dependencies = [ "serde", - "toml 0.8.15", + "toml 0.8.16", ] [[package]] @@ -769,6 +769,12 @@ dependencies = [ "syn 2.0.72", ] +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + [[package]] name = "dpi" version = "0.1.1" @@ -814,7 +820,7 @@ dependencies = [ "cc", "memchr", "rustc_version", - "toml 0.8.15", + "toml 0.8.16", "vswhom", "winreg", ] @@ -2840,9 +2846,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] @@ -2924,6 +2930,10 @@ dependencies = [ [[package]] name = "sesam-vitale" version = "0.1.0" +dependencies = [ + "dotenv", + "libc", +] [[package]] name = "sha2" @@ -3132,7 +3142,7 @@ dependencies = [ "cfg-expr", "heck 0.5.0", "pkg-config", - "toml 0.8.15", + "toml 0.8.16", "version-compare", ] @@ -3259,7 +3269,7 @@ dependencies = [ "serde_json", "tauri-utils", "tauri-winres", - "toml 0.8.15", + "toml 0.8.16", "walkdir", ] @@ -3376,7 +3386,7 @@ dependencies = [ "serde_with", "swift-rs", "thiserror", - "toml 0.8.15", + "toml 0.8.16", "url", "urlpattern", "walkdir", @@ -3539,21 +3549,21 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28" +checksum = "81967dd0dd2c1ab0bc3468bd7caecc32b8a4aa47d0c8c695d8c2b2108168d62c" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.16", + "toml_edit 0.22.17", ] [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "f8fb9f64314842840f1d940ac544da178732128f1c78c21772e876579e0da1db" dependencies = [ "serde", ] @@ -3584,15 +3594,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.16" +version = "0.22.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788" +checksum = "8d9f8729f5aea9562aac1cc0441f5d6de3cff1ee0c5d67293eeca5eb36ee7c16" dependencies = [ "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.15", + "winnow 0.6.16", ] [[package]] @@ -3879,9 +3889,9 @@ checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "vswhom" @@ -4443,9 +4453,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.15" +version = "0.6.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "557404e450152cd6795bb558bca69e43c585055f4606e3bcae5894fc6dac9ba0" +checksum = "b480ae9340fc261e6be3e95a1ba86d54ae3f9171132a73ce8d4bbaf68339507c" dependencies = [ "memchr", ] diff --git a/crates/sesam-vitale/.env.build.linux.example b/crates/sesam-vitale/.env.build.linux.example new file mode 100644 index 0000000..e7ab058 --- /dev/null +++ b/crates/sesam-vitale/.env.build.linux.example @@ -0,0 +1,3 @@ +SESAM_FSV_VERSION=1.40.13 +SESAM_FSV_LIB_PATH=/opt/santesocial/fsv/${SESAM_FSV_VERSION}/lib +SESAM_FSV_SSVLIB=ssvlux64 diff --git a/crates/sesam-vitale/.env.build.win.example b/crates/sesam-vitale/.env.build.win.example new file mode 100644 index 0000000..872ef1a --- /dev/null +++ b/crates/sesam-vitale/.env.build.win.example @@ -0,0 +1,3 @@ +SESAM_FSV_VERSION=1.40.13 +SESAM_FSV_LIB_PATH="C:/Program Files/santesocial/fsv/${SESAM_FSV_VERSION}/lib" +SESAM_FSV_SSVLIB=ssvw64 diff --git a/crates/sesam-vitale/.env.linux.example b/crates/sesam-vitale/.env.linux.example new file mode 100644 index 0000000..c8d84aa --- /dev/null +++ b/crates/sesam-vitale/.env.linux.example @@ -0,0 +1,2 @@ +SESAM_FSV_VERSION=1.40.13 +SESAM_INI_PATH=/etc/opt/santesocial/fsv/${SESAM_FSV_VERSION}/conf/sesam.ini diff --git a/crates/sesam-vitale/.env.win.example b/crates/sesam-vitale/.env.win.example new file mode 100644 index 0000000..bcd5177 --- /dev/null +++ b/crates/sesam-vitale/.env.win.example @@ -0,0 +1,2 @@ +SESAM_FSV_VERSION=1.40.13 +SESAM_INI_PATH=${ALLUSERSPROFILE}\\santesocial\\fsv\\${SESAM_FSV_VERSION}\\conf\\sesam.ini diff --git a/crates/sesam-vitale/.gitignore b/crates/sesam-vitale/.gitignore new file mode 100644 index 0000000..5c052ec --- /dev/null +++ b/crates/sesam-vitale/.gitignore @@ -0,0 +1,9 @@ +# Ignore Rust target directory +/target + +# Ignore .env files +.env +.env.build + +# Ignore exploitation files - only usefull for local debugging on windows +lib/*.exp diff --git a/crates/sesam-vitale/Cargo.toml b/crates/sesam-vitale/Cargo.toml index 7132546..e62b5db 100644 --- a/crates/sesam-vitale/Cargo.toml +++ b/crates/sesam-vitale/Cargo.toml @@ -4,3 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] +dotenv = "0.15" +libc = "0.2" + +[build-dependencies] +dotenv = "0.15" diff --git a/crates/sesam-vitale/README.md b/crates/sesam-vitale/README.md new file mode 100644 index 0000000..5638408 --- /dev/null +++ b/crates/sesam-vitale/README.md @@ -0,0 +1,34 @@ +## Requirements + +- Installer le [package FSV](https://industriels.sesam-vitale.fr/group/fournitures-sesam-vitale) + - Les librairies dynamiques (.lib, .dll, ...) fournies ne sont pas installés dans les emplacements standard du système, il faudra donc configurer leur chemin d'installation dans le fichier de configuration `.env.build` (voir ci-dessous) + - Le détail des chemins d'installation est donné dans la documentation du package FSV `fsv-mi-004_pack-FSV1.40.14_V2.3.pdf` + - Linux - par défaut : `/opt/santesocial/fsv/1.40.13/lib` + - Windows - par défaut : `C:\Program Files\santesocial\santesocial\fsv\1.40.14\lib` (ou dans Program Files (x86) si c'est le package 32bits qui a été installé) + +- Installer la [CryptolibCPS](https://industriels.sesam-vitale.fr/group/galss-cryptolib-cps) + - Ce package fourni également l'utilitaire "CPS Gestion" pour obtenir des informations sur le lecteur de carte, etc. + - Linux : `cpgeslux` + - Windows : `...` + +## Setup + +- Créer et éditer le fichier de configuration de build `.env.build` en s'inspirant d'un des fichiers d'exemple (`.env.build.linux.example`, `.env.build.win.example`...) + - Ce fichier est nécessaire pour le build du package Rust +- Créer et éditer le fichier de configuration de l'exécution `.env` en s'inspirant d'un des fichiers d'exemple (`.env.linux.example`, `.env.win.example`...) + - Ce fichier est nécessaire pour l'exécution du package Rust compilé, et doit donc être présent aux côtés de l'exécutable généré, le cas échéant + +## Build + +### Windows - Compilation des headers FSV + +Sous windows, la librairie dynamique fournie par le package FSV nécessite des headers qui ne sont pas présents dans la `.dll`. Il est donc nécessaire de fournir ces headers, en les renseignant dans des fichiers `crates/sesam-vitale/src/win/fsv/*.def` qui seront compilés en leur version binaire `crates/sesam-vitale/lib/*.lib`. + +En cas de modification des fichiers `.def`, pour re-compiler ces headers, faire appel au script `scripts/compile_win_headers.bat`. + +| /!\ Attention, le script `compile_win_headers.bat` exécute, en interne, l'utilitaire `vcvarsall.bat` et le linker `lib.exe` de Visual Studio. Visual Studio doit donc être installé et le chemin vers l'intallation le script `vcvarsall.bat`, écrit en dur dans le script `compile_win_headers.bat` doit être adapté à votre installation. + +## À creuser + +- Compilation cross platform facilitée par du Docker : https://github.com/cross-rs/cross +- Pour éviter l'usage de dotenv pour la configuration, on peut utiliser https://direnv.net/ diff --git a/crates/sesam-vitale/build.rs b/crates/sesam-vitale/build.rs new file mode 100644 index 0000000..60d9a3c --- /dev/null +++ b/crates/sesam-vitale/build.rs @@ -0,0 +1,36 @@ +extern crate dotenv; + +use std::env; +use std::path::PathBuf; + +fn main() { + // Load the .env.build file for build-time environment variables + let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + let manifest_path = PathBuf::from(manifest_dir); + dotenv::from_path(manifest_path.join(".env.build")).ok(); + + println!("cargo::rerun-if-env-changed=SESAM_FSV_LIB_PATH"); + println!("cargo::rerun-if-env-changed=SESAM_FSV_SSVLIB"); + println!("cargo::rerun-if-changed=.env.build"); + println!("cargo::rerun-if-changed=build.rs"); + + // Add local lib directory to the linker search path (for def files and static libs) + let static_lib_path = manifest_path.join("lib"); + println!("cargo::rustc-link-search=native={}", static_lib_path.display()); + + // Add the SESAM_FSV_LIB_PATH to the linker search path + let fsv_lib_path = PathBuf::from(env::var("SESAM_FSV_LIB_PATH").unwrap()); + println!("cargo::rustc-link-search=native={}", fsv_lib_path.display()); + + // Add the SESAM_FSV_LIB_PATH to the PATH environment variable + if cfg!(target_os = "windows") { + let path = env::var("PATH").unwrap_or(String::new()); + println!("cargo:rustc-env=PATH={};{}", fsv_lib_path.display(), path); + } else if cfg!(target_os = "linux") { + println!("cargo:rustc-env=LD_LIBRARY_PATH={}", fsv_lib_path.display()); + } + + // Link the SESAM_FSV_SSVLIB dynamic library + println!("cargo::rustc-link-lib=dylib={}", env::var("SESAM_FSV_SSVLIB").unwrap()); + // TODO : try `raw-dylib` instead of `dylib` on Windows to avoid the need of the `lib` headers compiled from the `def` +} diff --git a/crates/sesam-vitale/lib/.gitkeep b/crates/sesam-vitale/lib/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/crates/sesam-vitale/lib/ssvw64.lib b/crates/sesam-vitale/lib/ssvw64.lib new file mode 100644 index 0000000..13cbd5a Binary files /dev/null and b/crates/sesam-vitale/lib/ssvw64.lib differ diff --git a/crates/sesam-vitale/src/libssv.rs b/crates/sesam-vitale/src/libssv.rs new file mode 100644 index 0000000..7c3adf0 --- /dev/null +++ b/crates/sesam-vitale/src/libssv.rs @@ -0,0 +1,17 @@ +/** + * libssv.rs + * + * Low level bindings to the SSVLIB dynamic library. + * TODO : look for creating a dedicated *-sys crate : https://kornel.ski/rust-sys-crate + */ + +use libc::{ c_char, c_void, c_ushort, size_t }; + +#[cfg_attr(target_os = "linux", link(name = "ssvlux64"))] +#[cfg_attr(target_os = "windows", link(name = "ssvw64"))] +extern "C" { + pub fn SSV_InitLIB2(pcRepSesamIni: *const c_char) -> c_ushort; + pub fn SSV_LireCartePS(NomRessourcePS: *const c_char, NomRessourceLecteur: *const c_char, CodePorteurPS: *const c_char, ZDonneesSortie: *mut *mut c_void, TTailleDonneesSortie: *mut size_t) -> c_ushort; + pub fn SSV_LireConfig(ZDonneesSortie: *mut *mut c_void, TTailleDonneesSortie: *mut size_t) -> c_ushort; +} +/* TODO : replace void* by Rust struct : https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs */ diff --git a/crates/sesam-vitale/src/main.rs b/crates/sesam-vitale/src/main.rs new file mode 100644 index 0000000..b863fbb --- /dev/null +++ b/crates/sesam-vitale/src/main.rs @@ -0,0 +1,6 @@ +mod ssvlib_demo; +mod libssv; + +fn main() { + ssvlib_demo::demo(); +} diff --git a/crates/sesam-vitale/src/ssvlib_demo.rs b/crates/sesam-vitale/src/ssvlib_demo.rs new file mode 100644 index 0000000..a8f4731 --- /dev/null +++ b/crates/sesam-vitale/src/ssvlib_demo.rs @@ -0,0 +1,96 @@ +/** + * High level API for the SSV library, + * based on the low level bindings in libssv.rs. + * + */ + +extern crate libc; +extern crate dotenv; + +use libc::{ c_void, size_t }; +use std::ffi::CString; +use std::path::PathBuf; +use std::ptr; + +use std::env; + +use crate::libssv:: { + SSV_InitLIB2, + SSV_LireCartePS, + SSV_LireConfig +}; + +fn ssv_init_lib_2() { + let ini_str = env::var("SESAM_INI_PATH").expect("SESAM_INI_PATH must be set"); + let ini = CString::new(ini_str).expect("CString::new failed"); + unsafe { + let result = SSV_InitLIB2(ini.as_ptr()); + println!("SSV_InitLIB2 result: {}", result); + } +} + +fn ssv_lire_carte_ps() { + let resource_ps = CString::new("PS").expect("CString::new failed"); + let resource_reader = CString::new("TRANSPA1").expect("CString::new failed"); + let card_number = CString::new("1234567890").expect("CString::new failed"); + + let mut buffer: *mut c_void = ptr::null_mut(); + let mut size: size_t = 0; + unsafe { + let result = SSV_LireCartePS( + resource_ps.as_ptr(), + resource_reader.as_ptr(), + card_number.as_ptr(), + &mut buffer, + &mut size + ); + println!("SSV_LireCartePS result: {}", result); + + if !buffer.is_null() { + let hex_values = std::slice::from_raw_parts(buffer as *const u8, size); + for &byte in hex_values { + print!("{:02X} ", byte); + } + println!(); + + libc::free(buffer); + } + } +} + +fn ssv_lire_config() { + let mut buffer: *mut c_void = ptr::null_mut(); + let mut size: size_t = 0; + unsafe { + let result = SSV_LireConfig(&mut buffer, &mut size); + println!("SSV_LireConfig result: {}", result); + + if !buffer.is_null() { + let hex_values = std::slice::from_raw_parts(buffer as *const u8, size); + for &byte in hex_values { + print!("{:02X} ", byte); + } + println!(); + + libc::free(buffer); + } + } +} + +pub fn demo() { + /* + * TODO : this is probably not working on release, because I'm not sure it exists a CARGO_MANIFEST_DIR and so it can find the `.env` + * Maybe we could use a system standard config path to store a config file + */ + let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + let manifest_path = PathBuf::from(manifest_dir); + dotenv::from_path(manifest_path.join(".env")).ok(); + + println!("------- Demo for the SSV library --------"); + + ssv_init_lib_2(); + ssv_lire_carte_ps(); + ssv_lire_config(); + + println!("-----------------------------------------"); +} diff --git a/crates/sesam-vitale/src/win/fsv/ssvw64.def b/crates/sesam-vitale/src/win/fsv/ssvw64.def new file mode 100644 index 0000000..4d66637 --- /dev/null +++ b/crates/sesam-vitale/src/win/fsv/ssvw64.def @@ -0,0 +1,5 @@ +LIBRARY "ssvw64" +EXPORTS + SSV_InitLIB2 + SSV_LireCartePS + SSV_LireConfig diff --git a/scripts/compile_win_headers.bat b/scripts/compile_win_headers.bat new file mode 100644 index 0000000..2bde361 --- /dev/null +++ b/scripts/compile_win_headers.bat @@ -0,0 +1,26 @@ +@echo off +rem Set variables +set LIB_DIR=crates/sesam-vitale/lib +set DEF_DIR=crates/sesam-vitale/src/win/fsv + +if "%1"=="/clean" ( + goto clean +) + +rem Set the environment for the x64 platform +call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 + +rem Create a ssvw64.lib file from the ssvw64.def file +lib /def:ssvw64.def /out:%LIB_DIR%\ssvw64.lib /machine:x64 + +rem Build complete +pause +exit /b 0 + +:clean +del %LIB_DIR%\*.lib +del %LIB_DIR%\*.exp + +rem Clean complete +pause +exit /b 0