ext.rs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /*
  2. * Copyright (c)2021 ZeroTier, Inc.
  3. *
  4. * Use of this software is governed by the Business Source License included
  5. * in the LICENSE.TXT file in the project's root directory.
  6. *
  7. * Change Date: 2025-01-01
  8. *
  9. * On the date above, in accordance with the Business Source License, use
  10. * of this software will be governed by version 2.0 of the Apache License.
  11. */
  12. use std::ffi::{CStr, CString};
  13. use std::os::raw::c_char;
  14. use url::{Url};
  15. use crate::ZeroIDC;
  16. #[cfg(
  17. any(
  18. all(target_os = "linux", target_arch = "x86"),
  19. all(target_os = "linux", target_arch = "x86_64"),
  20. all(target_os = "linux", target_arch = "aarch64"),
  21. target_os = "windows",
  22. target_os = "macos",
  23. )
  24. )]
  25. #[no_mangle]
  26. pub extern "C" fn zeroidc_new(
  27. issuer: *const c_char,
  28. client_id: *const c_char,
  29. auth_endpoint: *const c_char,
  30. web_listen_port: u16,
  31. ) -> *mut ZeroIDC {
  32. if issuer.is_null() {
  33. println!("issuer is null");
  34. return std::ptr::null_mut();
  35. }
  36. if client_id.is_null() {
  37. println!("client_id is null");
  38. return std::ptr::null_mut();
  39. }
  40. if auth_endpoint.is_null() {
  41. println!("auth_endpoint is null");
  42. return std::ptr::null_mut();
  43. }
  44. let issuer = unsafe { CStr::from_ptr(issuer) };
  45. let client_id = unsafe { CStr::from_ptr(client_id) };
  46. let auth_endpoint = unsafe { CStr::from_ptr(auth_endpoint) };
  47. match ZeroIDC::new(
  48. issuer.to_str().unwrap(),
  49. client_id.to_str().unwrap(),
  50. auth_endpoint.to_str().unwrap(),
  51. web_listen_port,
  52. ) {
  53. Ok(idc) => {
  54. return Box::into_raw(Box::new(idc));
  55. }
  56. Err(s) => {
  57. println!("Error creating ZeroIDC instance: {}", s);
  58. return std::ptr::null_mut();
  59. }
  60. }
  61. }
  62. #[cfg(
  63. any(
  64. all(target_os = "linux", target_arch = "x86"),
  65. all(target_os = "linux", target_arch = "x86_64"),
  66. all(target_os = "linux", target_arch = "aarch64"),
  67. target_os = "windows",
  68. target_os = "macos",
  69. )
  70. )]
  71. #[no_mangle]
  72. pub extern "C" fn zeroidc_delete(ptr: *mut ZeroIDC) {
  73. if ptr.is_null() {
  74. return;
  75. }
  76. unsafe {
  77. Box::from_raw(ptr);
  78. }
  79. }
  80. #[cfg(
  81. any(
  82. all(target_os = "linux", target_arch = "x86"),
  83. all(target_os = "linux", target_arch = "x86_64"),
  84. all(target_os = "linux", target_arch = "aarch64"),
  85. target_os = "windows",
  86. target_os = "macos",
  87. )
  88. )]
  89. #[no_mangle]
  90. pub extern "C" fn zeroidc_start(ptr: *mut ZeroIDC) {
  91. let idc = unsafe {
  92. assert!(!ptr.is_null());
  93. &mut *ptr
  94. };
  95. idc.start();
  96. }
  97. #[cfg(
  98. any(
  99. all(target_os = "linux", target_arch = "x86"),
  100. all(target_os = "linux", target_arch = "x86_64"),
  101. all(target_os = "linux", target_arch = "aarch64"),
  102. target_os = "windows",
  103. target_os = "macos",
  104. )
  105. )]
  106. #[no_mangle]
  107. pub extern "C" fn zeroidc_stop(ptr: *mut ZeroIDC) {
  108. let idc = unsafe {
  109. assert!(!ptr.is_null());
  110. &mut *ptr
  111. };
  112. idc.stop();
  113. }
  114. #[cfg(
  115. any(
  116. all(target_os = "linux", target_arch = "x86"),
  117. all(target_os = "linux", target_arch = "x86_64"),
  118. all(target_os = "linux", target_arch = "aarch64"),
  119. target_os = "windows",
  120. target_os = "macos",
  121. )
  122. )]
  123. #[no_mangle]
  124. pub extern "C" fn zeroidc_is_running(ptr: *mut ZeroIDC) -> bool {
  125. let idc = unsafe {
  126. assert!(!ptr.is_null());
  127. &mut *ptr
  128. };
  129. idc.is_running()
  130. }
  131. #[no_mangle]
  132. pub extern "C" fn zeroidc_get_exp_time(ptr: *mut ZeroIDC) -> u64 {
  133. let id = unsafe {
  134. assert!(!ptr.is_null());
  135. &mut *ptr
  136. };
  137. id.get_exp_time()
  138. }
  139. #[cfg(
  140. any(
  141. all(target_os = "linux", target_arch = "x86"),
  142. all(target_os = "linux", target_arch = "x86_64"),
  143. all(target_os = "linux", target_arch = "aarch64"),
  144. target_os = "windows",
  145. target_os = "macos",
  146. )
  147. )]
  148. #[no_mangle]
  149. pub extern "C" fn zeroidc_set_nonce_and_csrf(
  150. ptr: *mut ZeroIDC,
  151. csrf_token: *const c_char,
  152. nonce: *const c_char) {
  153. let idc = unsafe {
  154. assert!(!ptr.is_null());
  155. &mut *ptr
  156. };
  157. if csrf_token.is_null() {
  158. println!("csrf_token is null");
  159. return;
  160. }
  161. if nonce.is_null() {
  162. println!("nonce is null");
  163. return;
  164. }
  165. let csrf_token = unsafe { CStr::from_ptr(csrf_token) }
  166. .to_str()
  167. .unwrap()
  168. .to_string();
  169. let nonce = unsafe { CStr::from_ptr(nonce) }
  170. .to_str()
  171. .unwrap()
  172. .to_string();
  173. idc.set_nonce_and_csrf(csrf_token, nonce);
  174. }
  175. #[cfg(
  176. any(
  177. all(target_os = "linux", target_arch = "x86"),
  178. all(target_os = "linux", target_arch = "x86_64"),
  179. all(target_os = "linux", target_arch = "aarch64"),
  180. target_os = "windows",
  181. target_os = "macos",
  182. )
  183. )]
  184. #[no_mangle]
  185. pub extern "C" fn free_cstr(s: *mut c_char) {
  186. if s.is_null() {
  187. println!("passed a null object");
  188. return;
  189. }
  190. unsafe {
  191. let _ = CString::from_raw(s);
  192. }
  193. }
  194. #[cfg(
  195. any(
  196. all(target_os = "linux", target_arch = "x86"),
  197. all(target_os = "linux", target_arch = "x86_64"),
  198. all(target_os = "linux", target_arch = "aarch64"),
  199. target_os = "windows",
  200. target_os = "macos",
  201. )
  202. )]
  203. #[no_mangle]
  204. pub extern "C" fn zeroidc_get_auth_url(ptr: *mut ZeroIDC) -> *mut c_char {
  205. if ptr.is_null() {
  206. println!("passed a null object");
  207. return std::ptr::null_mut();
  208. }
  209. let idc = unsafe {
  210. &mut *ptr
  211. };
  212. let s = CString::new(idc.auth_url()).unwrap();
  213. return s.into_raw();
  214. }
  215. #[cfg(
  216. any(
  217. all(target_os = "linux", target_arch = "x86"),
  218. all(target_os = "linux", target_arch = "x86_64"),
  219. all(target_os = "linux", target_arch = "aarch64"),
  220. target_os = "windows",
  221. target_os = "macos",
  222. )
  223. )]
  224. #[no_mangle]
  225. pub extern "C" fn zeroidc_token_exchange(idc: *mut ZeroIDC, code: *const c_char ) -> *mut c_char {
  226. if idc.is_null() {
  227. println!("idc is null");
  228. return std::ptr::null_mut();
  229. }
  230. if code.is_null() {
  231. println!("code is null");
  232. return std::ptr::null_mut();
  233. }
  234. let idc = unsafe {
  235. &mut *idc
  236. };
  237. let code = unsafe{CStr::from_ptr(code)}.to_str().unwrap();
  238. let ret = idc.do_token_exchange( code);
  239. let ret = CString::new(ret).unwrap();
  240. return ret.into_raw();
  241. }
  242. #[no_mangle]
  243. pub extern "C" fn zeroidc_get_url_param_value(param: *const c_char, path: *const c_char) -> *mut c_char {
  244. if param.is_null() {
  245. println!("param is null");
  246. return std::ptr::null_mut();
  247. }
  248. if path.is_null() {
  249. println!("path is null");
  250. return std::ptr::null_mut();
  251. }
  252. let param = unsafe {CStr::from_ptr(param)}.to_str().unwrap();
  253. let path = unsafe {CStr::from_ptr(path)}.to_str().unwrap();
  254. let url = "http://localhost:9993".to_string() + path;
  255. let url = Url::parse(&url).unwrap();
  256. let pairs = url.query_pairs();
  257. for p in pairs {
  258. if p.0 == param {
  259. let s = CString::new(p.1.into_owned()).unwrap();
  260. return s.into_raw()
  261. }
  262. }
  263. return std::ptr::null_mut();
  264. }
  265. #[no_mangle]
  266. pub extern "C" fn zeroidc_network_id_from_state(state: *const c_char) -> *mut c_char {
  267. if state.is_null() {
  268. println!("state is null");
  269. return std::ptr::null_mut();
  270. }
  271. let state = unsafe{CStr::from_ptr(state)}.to_str().unwrap();
  272. let split = state.split("_");
  273. let split = split.collect::<Vec<&str>>();
  274. if split.len() != 2 {
  275. return std::ptr::null_mut();
  276. }
  277. let s = CString::new(split[1]).unwrap();
  278. return s.into_raw();
  279. }
  280. #[cfg(
  281. any(
  282. all(target_os = "linux", target_arch = "x86"),
  283. all(target_os = "linux", target_arch = "x86_64"),
  284. all(target_os = "linux", target_arch = "aarch64"),
  285. target_os = "windows",
  286. target_os = "macos",
  287. )
  288. )]
  289. #[no_mangle]
  290. pub extern "C" fn zeroidc_kick_refresh_thread(idc: *mut ZeroIDC) {
  291. if idc.is_null() {
  292. println!("idc is null");
  293. return;
  294. }
  295. let idc = unsafe {
  296. &mut *idc
  297. };
  298. idc.kick_refresh_thread();
  299. }