From 4cd6da64dfe6d889f811c52e485e1e0f711be820 Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Tue, 20 Mar 2018 02:30:38 +0100 Subject: [PATCH 1/3] Runtime: add hex() --- src/ctx.rs | 31 +++++++++++++++++++++++++++++++ src/runtime.rs | 20 ++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/ctx.rs b/src/ctx.rs index e8bfc01..ff32215 100644 --- a/src/ctx.rs +++ b/src/ctx.rs @@ -69,6 +69,7 @@ impl Script { let state = State::new(); runtime::execve(&mut lua, state.clone()); + runtime::hex(&mut lua, state.clone()); runtime::http_basic_auth(&mut lua, state.clone()); runtime::ldap_bind(&mut lua, state.clone()); runtime::ldap_escape(&mut lua, state.clone()); @@ -194,4 +195,34 @@ mod tests { let result = script.run_once("invalid", "wrong").unwrap(); assert!(!result); } + + #[test] + fn verify_hex() { + let script = Script::load_from(r#" + descr = "hex test" + + function verify(user, password) + x = hex({0x6F, 0x68, 0x61, 0x69, 0x0A, 0x00}) + return x == "6f6861690a00" + end + "#.as_bytes()).unwrap(); + + let result = script.run_once("x", "x").unwrap(); + assert!(result); + } + + #[test] + fn verify_hex_empty() { + let script = Script::load_from(r#" + descr = "hex test" + + function verify(user, password) + x = hex({}) + return x == "" + end + "#.as_bytes()).unwrap(); + + let result = script.run_once("x", "x").unwrap(); + assert!(result); + } } diff --git a/src/runtime.rs b/src/runtime.rs index c26903b..2fd479c 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -41,6 +41,26 @@ pub fn execve(lua: &mut hlua::Lua, state: State) { })) } +pub fn hex(lua: &mut hlua::Lua, _state: State) { + lua.set("hex", hlua::function1(move |bytes: Vec| -> Result { + let mut out = String::new(); + + for num in bytes { + match num { + AnyLuaValue::LuaNumber(num) => { + if num > 255.0 || num < 0.0 { + return Err(format!("number is out of range: {:?}", num).into()); + } + out += &format!("{:02x}", num as u8); + }, + _ => return Err(format!("unexpected type: {:?}", num).into()), + } + } + + Ok(out) + })) +} + pub fn http_basic_auth(lua: &mut hlua::Lua, state: State) { lua.set("http_basic_auth", hlua::function3(move |url: String, user: String, password: String| -> Result { let client = reqwest::Client::new(); From 1a53d370e9148e38ebc471c369a7653462d8ff41 Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Wed, 21 Mar 2018 20:21:03 +0100 Subject: [PATCH 2/3] Add last_err for error handling --- README.md | 7 +++++++ docs/badtouch.1 | 9 +++++++++ src/ctx.rs | 9 +++++++++ src/runtime.rs | 9 +++++++++ 4 files changed, 34 insertions(+) diff --git a/README.md b/README.md index fa55b0c..3e1e3c6 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ magically provided by the badtouch runtime. ## Reference - [execve](#execve) - [http_basic_auth](#http_basic_auth) +- [last_err](#last_err) - [ldap_bind](#ldap_bind) - [ldap_escape](#ldap_escape) - [mysql_connect](#mysql_connect) @@ -46,6 +47,12 @@ header is set and the status code is not `401`. http_basic_auth("https://httpbin.org/basic-auth/foo/buzz", user, password) ``` +### last_err +Returns `nil` if no error has been recorded, returns a string otherwise. +```lua +if last_err() then return end +``` + ### ldap_bind Connect to an ldap server and try to authenticate with the given user ```lua diff --git a/docs/badtouch.1 b/docs/badtouch.1 index 2ad324a..786588b 100644 --- a/docs/badtouch.1 +++ b/docs/badtouch.1 @@ -74,6 +74,15 @@ Sends a \fBGET\fR request with basic auth. Returns \fBtrue\fR if no .fi .RE +.SS last_err +.LP +Returns \fBnil\fR if no error has been recorded, returns a string otherwise. +.RS +.nf +\fBif last_err() then return end\fP +.fi +.RE + .SS ldap_bind .LP Connect to an ldap server and try to authenticate with the given user diff --git a/src/ctx.rs b/src/ctx.rs index ff32215..f454343 100644 --- a/src/ctx.rs +++ b/src/ctx.rs @@ -19,6 +19,14 @@ impl State { } } + pub fn last_error(&self) -> Option { + let lock = self.error.lock().unwrap(); + match *lock { + Some(ref err) => Some(err.to_string()), + None => None, + } + } + pub fn set_error(&self, err: Error) -> Error { let mut mtx = self.error.lock().unwrap(); let cp = err.to_string(); @@ -71,6 +79,7 @@ impl Script { runtime::execve(&mut lua, state.clone()); runtime::hex(&mut lua, state.clone()); runtime::http_basic_auth(&mut lua, state.clone()); + runtime::last_err(&mut lua, state.clone()); runtime::ldap_bind(&mut lua, state.clone()); runtime::ldap_escape(&mut lua, state.clone()); runtime::ldap_search_bind(&mut lua, state.clone()); diff --git a/src/runtime.rs b/src/runtime.rs index 2fd479c..6b461b7 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -84,6 +84,15 @@ pub fn http_basic_auth(lua: &mut hlua::Lua, state: State) { })) } +pub fn last_err(lua: &mut hlua::Lua, state: State) { + lua.set("last_err", hlua::function0(move || -> AnyLuaValue { + match state.last_error() { + Some(err) => AnyLuaValue::LuaString(err), + None => AnyLuaValue::LuaNil, + } + })) +} + pub fn ldap_bind(lua: &mut hlua::Lua, state: State) { lua.set("ldap_bind", hlua::function3(move |url: String, dn: String, password: String| -> Result { let sock = match ldap3::LdapConn::new(&url) From 34fdec73e8ac3bdce624801423638cba350a3c5a Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Wed, 21 Mar 2018 20:24:17 +0100 Subject: [PATCH 3/3] Document execve error handling --- README.md | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 3e1e3c6..70cd1dc 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,14 @@ out to your regular python script occasionally. Your wrapper my look like this: descr = "example.com" function verify(user, password) - return execve("./docs/test.sh", {user, password}) == 0 + ret = execve("./docs/test.sh", {user, password}) + if last_err() then return end + + if ret == 2 then + return "script signaled an exception" + end + + return ret == 0 end ``` @@ -120,12 +127,17 @@ Your python script may look like this: ```python import sys -if sys.argv[1] == "foo" and sys.argv[2] == "bar": - # correct credentials - exit(0) -else: - # incorrect credentials - exit(1) +try: + if sys.argv[1] == "foo" and sys.argv[2] == "bar": + # correct credentials + exit(0) + else: + # incorrect credentials + exit(1) +except: + # signal an exception + # this requeues the attempt instead of discarding it + exit(2) ``` # License