转换 SID 二进制和字符串形式:https://devblogs.microsoft.com/oldnewthing/20040315-00/?p=40253
CREATE OR REPLACE FUNCTION get_objectsid (p_samaccount IN VARCHAR2)
RETURN VARCHAR2 AS
v_objectguid VARCHAR2(100) := NULL;
v_ldap_host VARCHAR2(256) := 'server.domain.base';
v_ldap_port VARCHAR2(256) := '389';
v_ldap_user VARCHAR2(256) := 'CN=Oracle Services,OU=OtherAccounts,OU=Corporate,OU=Locations,DC=domain,DC=base';
v_ldap_passwd VARCHAR2(256) := 'password';
v_ldap_base VARCHAR2(256) := 'DC=domain,DC=base';
v_result PLS_INTEGER;
v_session DBMS_LDAP.session;
v_search_attrs DBMS_LDAP.string_collection;
v_search_results DBMS_LDAP.MESSAGE;
v_entry DBMS_LDAP.MESSAGE;
v_values DBMS_LDAP.BINVAL_COLLECTION;
v_ber_element dbms_ldap.ber_element;
v_attr_name VARCHAR2(256);
l_revision number;
l_num_dashes number;
l_sid_issue_authority number;
l_object_sid varchar2(100);
function endian_value(p_string varchar2, p_endian_type varchar2)
return varchar2
as
l_step number := 2;
l_val varchar2(4000);
begin
if upper(p_endian_type) = 'L' then
for i in 1..length(p_string) / 2
loop
l_val := substr(p_string, i * l_step - 1, 2)||l_val;
dbms_output.put_line('endian of '||l_val);
end loop;
else
l_val := p_string;
end if;
return to_number(l_val, 'xxxxxxxxxxxxxxxx');
end;
function process_left(p_string in out varchar2, p_len int)
return varchar2
as
l_rtn varchar2(100);
begin
l_rtn := substr(p_string, 1, p_len);
p_string := substr(p_string, p_len + 1);
return l_rtn;
end;
BEGIN
-- Choose to raise exceptions.
DBMS_LDAP.use_exception := TRUE;
-- initiating the connection to the LDAP server
v_session := DBMS_LDAP.init(hostname => v_ldap_host, portnum => v_ldap_port);
-- binding the user
v_result := DBMS_LDAP.simple_bind_s(ld => v_session,
dn => v_ldap_user,
passwd => v_ldap_passwd);
-- attribute name to search
v_search_attrs(1) := 'objectSid';
v_result := DBMS_LDAP.search_s( ld => v_session,
base => v_ldap_base,
scope => DBMS_LDAP.SCOPE_SUBTREE,
FILTER => '(&(objectClass=user)(samaccountName='||p_samaccount||'))',
attrs => v_search_attrs,
attronly => 0,
res => v_search_results);
-- expecting there will be only one entry matched , one attribute objectGUID only
IF dbms_ldap.count_entries(ld => v_session, msg => v_search_results) > 0
THEN
v_entry := DBMS_LDAP.first_entry(ld => v_session, msg => v_search_results);
v_attr_name := dbms_ldap.first_attribute(ld => v_session,
ldapentry => v_entry,
ber_elem => v_ber_element);
v_values := dbms_ldap.get_values_len (ld => v_session,
ldapentry => v_entry,
attr => v_attr_name);
IF v_values.COUNT > 0
THEN
FOR i IN v_values.FIRST .. v_values.LAST
LOOP
select rawtohex(v_values(i)) into v_objectguid from dual;
END LOOP;
END IF;
dbms_output.put_line(v_objectguid);
l_revision := to_number(process_left(v_objectguid, 2), '00');
l_num_dashes := to_number(process_left(v_objectguid, 2), '00');
l_sid_issue_authority := endian_value(process_left(v_objectguid, 12), 'b');
l_object_sid := 'S-'||l_revision||'-'||l_sid_issue_authority;
for i in 1..to_number(l_num_dashes)
loop
l_object_sid := l_object_sid||'-'||endian_value(process_left(v_objectguid, 8), 'l');
end loop;
dbms_output.put_line(l_object_sid);
END IF;
IF l_object_sid IS NULL THEN
l_object_sid:='No_objectsid';
END IF;
IF v_entry IS NOT NULL THEN
v_result := DBMS_LDAP.msgfree(v_entry);
END IF;
v_result := DBMS_LDAP.unbind_s(ld => v_session);
RETURN l_object_sid;
EXCEPTION
WHEN NO_DATA_FOUND THEN
l_object_sid:='---NoSid---';
RETURN l_object_sid;
END get_objectsid;