Skip to content

feat: new rust decoder #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Mar 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,12 @@ jobs:
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo docker run hello-world

# rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y

# luarocks
sudo apt -y install lua5.1 luarocks
sudo luarocks install lua_pack
sudo luarocks install lpeg
luarocks make rockspec/lua-resty-ldap-local-0.rockspec --local --tree ./deps # install deps to local

- name: script
run: |
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
# dev
t/servroot


# Added by cargo

/target
/Cargo.lock
17 changes: 17 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "lua-resty-ldap"
version = "0.1.0"
edition = "2021"

[lib]
name = "rasn"
crate-type = ["cdylib"]

[dependencies]
mlua = { version = "0.8.6", features = ["module", "send", "luajit"] }
rasn = "0.6.1"
rasn-ldap = "0.6.0"
bytes = "1.4.0"

[profile.release]
strip = true
30 changes: 25 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,17 +1,37 @@
PREFIX ?= /usr/local/openresty
LUA_LIB_DIR ?= $(PREFIX)/lualib/$(LUA_VERSION)
INSTALL ?= install
ECHO ?= echo

all:
@echo --- Build
@echo CFLAGS: $(CFLAGS)
@echo LIBFLAG: $(LIBFLAG)
@echo LUA_LIBDIR: $(LUA_LIBDIR)
@echo LUA_BINDIR: $(LUA_BINDIR)
@echo LUA_INCDIR: $(LUA_INCDIR)

@echo --- Check Rust toolchain
@utils/check-rust.sh

@echo --- Build Rust cdylib
cargo build --release

### install: Install the library to runtime
.PHONY: install
install:
$(INSTALL) -d $(DESTDIR)/$(LUA_LIB_DIR)/resty/ldap/
$(INSTALL) lib/resty/*.lua $(DESTDIR)/$(LUA_LIB_DIR)/resty/ldap/
@echo --- Install
@echo INST_PREFIX: $(INST_PREFIX)
@echo INST_BINDIR: $(INST_BINDIR)
@echo INST_LIBDIR: $(INST_LIBDIR)
@echo INST_LUADIR: $(INST_LUADIR)
@echo INST_CONFDIR: $(INST_CONFDIR)
$(INSTALL) -d $(INST_LUADIR)/resty/ldap/
$(INSTALL) lib/resty/ldap/*.lua $(INST_LUADIR)/resty/ldap/
$(INSTALL) target/release/librasn.so $(INST_LIBDIR)/rasn.so

### dev: Create a development ENV
.PHONY: dev
dev:
luarocks install rockspec/lua-resty-ldap-main-0.1-0.rockspec --only-deps --local
luarocks install rockspec/lua-resty-ldap-main-0.rockspec --only-deps --local

### help: Show Makefile rules
.PHONY: help
Expand Down
21 changes: 14 additions & 7 deletions lib/resty/ldap/client.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ local bunpack = require("lua_pack").unpack
local protocol = require("resty.ldap.protocol")
local asn1 = require("resty.ldap.asn1")
local to_hex = require("resty.string").to_hex
local rasn = require("rasn")

local tostring = tostring
local fmt = string.format
Expand All @@ -11,6 +12,7 @@ local DEBUG = ngx.DEBUG
local tcp = ngx.socket.tcp
local table_insert = table.insert
local string_char = string.char
local rasn_decode = rasn.decode_ldap

local asn1_parse_ldap_result = asn1.parse_ldap_result

Expand Down Expand Up @@ -38,7 +40,7 @@ local function calculate_payload_length(encStr, pos, socket)
elen = elenCalc
end

return pos, elen
return pos, elen, encStr
end

local function _start_tls(sock, host, port)
Expand Down Expand Up @@ -173,7 +175,7 @@ local function _send_recieve(cli, request, multi_resp_hint)
end
break -- read done, data has been taken to the end
end
local _, packet_len = calculate_payload_length(len, 2, socket)
local _, packet_len, packet_header = calculate_payload_length(len, 2, socket)

-- Get the data of the specified length
local packet, err = socket:receive(packet_len)
Expand All @@ -184,10 +186,17 @@ local function _send_recieve(cli, request, multi_resp_hint)
socket:close()
return nil, err
end
local res, err = asn1_parse_ldap_result(packet)
if err then
return nil, fmt("invalid ldap message encoding: %s, message: %s", err, to_hex(packet))

local packet = packet_header .. packet
local ok, res, err = pcall(rasn_decode, packet)
if not ok or err then
return nil, fmt(
"failed to decode ldap message: %s, message: %s",
not ok and res or err, -- error returned in second value by pcall
to_hex(packet)
)
end

table_insert(result, res)

-- This is an ugly patch to actively stop continuous reading. When a search
Expand Down Expand Up @@ -297,8 +306,6 @@ function _M.search(self, base_dn, scope, deref_aliases, size_limit, time_limit,
item.diagnostic_msg or "")
end
res[index] = nil
else
res[index] = item.search_entries
end
end

Expand Down
36 changes: 36 additions & 0 deletions rockspec/lua-resty-ldap-local-0.rockspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package = "lua-resty-ldap"
version = "local-0"
source = {
url = "file://."
}

description = {
summary = "Nonblocking Lua ldap driver library for OpenResty",
homepage = "https://github.com/api7/lua-resty-ldap",
license = "Apache License 2.0",
maintainer = "Yuansheng Wang <[email protected]>"
}

dependencies = {
"lua_pack = 2.0.0-0",
"lpeg = 1.0.2-1",
}

build = {
type = "make",
build_variables = {
CFLAGS="$(CFLAGS)",
LIBFLAG="$(LIBFLAG)",
LUA_LIBDIR="$(LUA_LIBDIR)",
LUA_BINDIR="$(LUA_BINDIR)",
LUA_INCDIR="$(LUA_INCDIR)",
LUA="$(LUA)",
},
install_variables = {
INST_PREFIX="$(PREFIX)",
INST_BINDIR="$(BINDIR)",
INST_LIBDIR="$(LIBDIR)",
INST_LUADIR="$(LUADIR)",
INST_CONFDIR="$(CONFDIR)",
},
}
25 changes: 17 additions & 8 deletions rockspec/lua-resty-ldap-main-0.rockspec
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,24 @@ description = {

dependencies = {
"lua_pack = 2.0.0-0",
"lpeg = 1.0.2-1"
"lpeg = 1.0.2-1",
}

build = {
type = "builtin",
modules = {
["resty.ldap.client"] = "lib/resty/ldap/client.lua",
["resty.ldap.protocol"] = "lib/resty/ldap/protocol.lua",
["resty.ldap.filter"] = "lib/resty/ldap/filter.lua",
["resty.ldap.asn1"] = "lib/resty/ldap/asn1.lua",
}
type = "make",
build_variables = {
CFLAGS="$(CFLAGS)",
LIBFLAG="$(LIBFLAG)",
LUA_LIBDIR="$(LUA_LIBDIR)",
LUA_BINDIR="$(LUA_BINDIR)",
LUA_INCDIR="$(LUA_INCDIR)",
LUA="$(LUA)",
},
install_variables = {
INST_PREFIX="$(PREFIX)",
INST_BINDIR="$(BINDIR)",
INST_LIBDIR="$(LIBDIR)",
INST_LUADIR="$(LUADIR)",
INST_CONFDIR="$(CONFDIR)",
},
}
101 changes: 101 additions & 0 deletions src/ldap_codec/decoder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
use mlua::prelude::{Lua, LuaResult, LuaValue};
use bytes::Bytes;
use rasn::der;
use rasn_ldap::{LdapMessage, ProtocolOp};

fn bytes_to_string(b: Bytes) -> Result<String, std::string::FromUtf8Error> {
return String::from_utf8(b.to_vec());
}

pub fn decode<'lua>(
lua: &'lua Lua,
v: LuaValue<'lua>,
) -> LuaResult<(LuaValue<'lua>, LuaValue<'lua>)> {
let der = match v {
LuaValue::String(v) => v,
_ => {
return Ok((
LuaValue::Nil,
LuaValue::String(lua.create_string("wrong format on input data")?),
))
}
};

let lm = match der::decode::<LdapMessage>(der.as_bytes()) {
Ok(lm) => lm,
Err(err) => {
let err_str = format!("{}", err.to_string());

return Ok((
LuaValue::Nil,
LuaValue::String(lua.create_string(err_str.as_bytes())?),
));
}
};

let result = lua.create_table()?;
match lm.protocol_op {
ProtocolOp::BindResponse(resp) => {
result.set("protocol_op", 1)?;
result.set("result_code", resp.result_code as i64)?;
result.set("matched_dn", bytes_to_string(resp.matched_dn).unwrap())?;
result.set(
"diagnostic_msg",
bytes_to_string(resp.diagnostic_message).unwrap(),
)?;
return Ok((LuaValue::Table(result), LuaValue::Nil));
}
ProtocolOp::SearchResEntry(entry) => {
result.set("protocol_op", 4)?;
result.set("entry_dn", bytes_to_string(entry.object_name).unwrap())?;

let attributes = lua.create_table()?;
for attribute in entry.attributes.into_iter() {
let attribute_vals = lua.create_table()?;
for val in attribute.vals.into_iter() {
attribute_vals.push(bytes_to_string(val).unwrap())?
}
attributes.set(bytes_to_string(attribute.r#type).unwrap(), attribute_vals)?;
}

result.set("attributes", attributes)?;
return Ok((LuaValue::Table(result), LuaValue::Nil));
}
ProtocolOp::SearchResDone(done) => {
let resp = done.0;
result.set("protocol_op", 5)?;
result.set("result_code", resp.result_code as i64)?;
result.set("matched_dn", bytes_to_string(resp.matched_dn).unwrap())?;
result.set(
"diagnostic_msg",
bytes_to_string(resp.diagnostic_message).unwrap(),
)?;
return Ok((LuaValue::Table(result), LuaValue::Nil));
}
ProtocolOp::ModifyResponse(resp0) => {
let resp = resp0.0;
result.set("protocol_op", 7)?;
result.set("result_code", resp.result_code as i64)?;
result.set("matched_dn", bytes_to_string(resp.matched_dn).unwrap())?;
result.set(
"diagnostic_msg",
bytes_to_string(resp.diagnostic_message).unwrap(),
)?;
return Ok((LuaValue::Table(result), LuaValue::Nil));
}
ProtocolOp::SearchResRef(_) => {
return Ok((
LuaValue::Nil,
LuaValue::String(
lua.create_string("decoder not yet implement: search result reference")?,
),
))
}
_ => {
return Ok((
LuaValue::Nil,
LuaValue::String(lua.create_string("decoder not yet implement")?),
))
}
}
}
11 changes: 11 additions & 0 deletions src/ldap_codec/encoder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use mlua::prelude::{Lua, LuaResult, LuaValue};

pub fn encode<'lua>(
lua: &'lua Lua,
_: LuaValue<'lua>,
) -> LuaResult<(LuaValue<'lua>, LuaValue<'lua>)> {
Ok((
LuaValue::Nil,
LuaValue::String(lua.create_string("not yet implement")?),
))
}
2 changes: 2 additions & 0 deletions src/ldap_codec/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub mod encoder;
pub mod decoder;
14 changes: 14 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use ldap_codec::{decoder::decode, encoder::encode};
use mlua::prelude::{Lua, LuaResult, LuaTable};

mod ldap_codec;

#[mlua::lua_module]
fn rasn(lua: &Lua) -> LuaResult<LuaTable> {
let exports = lua.create_table()?;

exports.set("encode_ldap", lua.create_function(encode)?)?;
exports.set("decode_ldap", lua.create_function(decode)?)?;

Ok(exports)
}
3 changes: 2 additions & 1 deletion t/client.t
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ repeat_each(1);
plan 'no_plan';

our $HttpConfig = <<'_EOC_';
lua_package_path 'lib/?.lua;lib/?/init.lua;/usr/local/share/lua/5.3/?.lua;/usr/share/lua/5.1/?.lua;;';
lua_package_path 'lib/?.lua;/usr/share/lua/5.1/?.lua;;';
lua_package_cpath 'deps/lib/lua/5.1/?.so;;';
resolver 127.0.0.53;
_EOC_

Expand Down
3 changes: 2 additions & 1 deletion t/filter.t
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ repeat_each(1);
plan 'no_plan';

our $HttpConfig = <<'_EOC_';
lua_package_path 'lib/?.lua;lib/?/init.lua;/usr/local/share/lua/5.3/?.lua;/usr/share/lua/5.1/?.lua;;';
lua_package_path 'lib/?.lua;/usr/share/lua/5.1/?.lua;;';
lua_package_cpath 'deps/lib/lua/5.1/?.so;;';
resolver 127.0.0.53;
_EOC_

Expand Down
Loading