From: Torbjorn T. <et...@us...> - 2005-01-04 19:20:20
|
Update of /cvsroot/jungerl/jungerl/lib/esmb/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30864 Modified Files: esmb.erl esmb_client.erl esmb_lib.hrl esmb_rpc.erl Log Message: SMB signing now seem to work. Index: esmb_rpc.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/esmb/src/esmb_rpc.erl,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- esmb_rpc.erl 15 Oct 2004 10:49:06 -0000 1.1 +++ esmb_rpc.erl 4 Jan 2005 19:19:47 -0000 1.2 @@ -16,13 +16,15 @@ -module(esmb_rpc). -export([rpc_samr_connect/3, rpc_samr_close/3, rpc_samr_enum_doms/3, rpc_samr_lookup_doms/4, rpc_samr_lookup_names/5, - rpc_samr_open_user/5, open_srvsvc_pipe/2, open_samr_pipe/2, - rpc_netr_share_enum/3]). + rpc_samr_open_domain/5, rpc_samr_user_groups/4, + rpc_samr_open_user/5, rpc_samr_open_user/6, + open_srvsvc_pipe/2, open_samr_pipe/2, rpc_samr_lookup_rids/5, + rpc_netr_share_enum/3, rpc_bind/3]). %%% For testing --export([test/0,test/1,test2/0,test2/1]). +-export([test/0,skrak/0,test/3,test2/0,test2/1]). --import(esmb, [unicode_p/1, to_ucs2/2, to_ucs2_and_null/2]). +-import(esmb, [unicode_p/1, to_ucs2/2, to_ucs2_and_null/2, ucs2_to_ascii/1]). -import(esmb, [b2l/1, hexprint/1]). -include("esmb_lib.hrl"). @@ -58,17 +60,22 @@ -%%% @hidden -%%% -%%% List shares on server -%%% +%%% @hidden test() -> - test("192.168.128.65"). + test("192.168.128.65", "tobbe", "qwe123"). -test(Host) -> +%%% @hidden +skrak() -> + test("192.168.128.42", "tobbe", "qwe123"). + +%%% @hidden +test(Host, User, Passwd) -> + %% + %% List shares on server + %% {ok,S,Neg} = esmb:connect(Host), - U = #user{pw = "qwe123", name = "tobbe"}, + U = #user{pw = Passwd, name = User}, Pdu0 = esmb:user_logon(S, Neg, U), esmb:exit_if_error(Pdu0, "Login failed"), IPC = "\\\\"++Host++"\\IPC"++[$$], @@ -102,14 +109,14 @@ %%% @hidden - -%%% -%%% NTLM authenticate user -%%% test2() -> test2("192.168.128.65"). +%%% @hidden test2(Host) -> + %% + %% NTLM authenticate user + %% {ok,S,Neg} = esmb:connect(Host), U = #user{pw = "qwe123", name = "tobbe"}, Pdu0 = esmb:user_logon(S, Neg, U), @@ -119,7 +126,7 @@ Pdu1 = esmb:tree_connect(S, Neg, Pdu0, Path1, ?SERVICE_NAMED_PIPE), esmb:exit_if_error(Pdu1, "Tree connect failed"), %% - Pdu2 = open_samr_pipe(S, Pdu1), + {ok,Pdu2} = open_samr_pipe(S, Pdu1), %% rpc_bind(S, Pdu2, ?ST_SAMR), IpStr = "\\\\192.168.128.51", % FIXME @@ -187,22 +194,24 @@ %%% %%% @spec open_srvsvc_pipe(S::socket(), PDU::pdu()) -> -%%% pdu() | exception() +%%% {ok,pdu()} | exception() %%% %%% @doc Opens up the <em>srvsvc</em> pipe (NT Administrative %%% Services). This is the first thing that needs to be %%% done before any DCE/RPC requests can be issued. +%%% The returned pdu() record will contain the <em>FID</em> +%%% file descriptor. %%% @end %%% open_srvsvc_pipe(S, Pdu0) -> - Path = to_ucs2(unicode_p(Pdu0), "\\\\srvsvc"), + Path = to_ucs2(unicode_p(Pdu0), "\\srvsvc"), Pdu1 = esmb:open_file_rw(S, Pdu0, Path), - esmb:exit_if_error(Pdu0, "Open srvsvc pipe, failed"), - Pdu1. + esmb:exit_if_error(Pdu1, "Open srvsvc pipe, failed"), + {ok,Pdu1}. %%% %%% @spec open_samr_pipe(S::socket(), PDU::pdu()) -> -%%% pdu() | exception() +%%% {ok,pdu()} | exception() %%% %%% @doc Opens up the <em>samr</em> pipe (NT SAM Database %%% Management Services). This is the first thing that @@ -211,16 +220,16 @@ %%% @end %%% open_samr_pipe(S, Pdu0) -> - Path = to_ucs2(unicode_p(Pdu0), "\\\\samr"), + Path = to_ucs2(unicode_p(Pdu0), "\\samr"), Pdu1 = esmb:open_file_rw(S, Pdu0, Path), esmb:exit_if_error(Pdu0, "Open samr pipe, failed"), - Pdu1. + {ok,Pdu1}. %%% %%% @spec rpc_bind(S::socket(), PDU::pdu(), %%% ST::serviceType()) -> -%%% ok | exception() +%%% {ok, pdu()} | exception() %%% %%% @doc This is where a RPC connection is setup. %%% The <em>ServiceType</em> input argument defines @@ -229,10 +238,10 @@ %%% rpc_bind(S, Pdu, ServiceType) -> Rpc = e_rpc_bind(ServiceType), - {ok,BindRes} = esmb:named_pipe_transaction(S, Pdu, Rpc), + {ok,BindRes,Pdu2} = esmb:named_pipe_transaction(S, Pdu, Rpc), case catch d_bind_response(BindRes) of Ack when record(Ack, rpc_bind_ack) -> - ok; + {ok,Pdu2}; Else -> throw({error, Else}) end. @@ -241,28 +250,28 @@ %%% %%% @spec rpc_netr_share_enum(S::socket(), PDU::pdu(), %%% IpStr::string()) -> -%%% nseEntries() | exception() +%%% {ok, nseEntries(), pdu()} | exception() %%% %%% @doc The <em>NetrShareEnum</em> request is used to retrieve %%% information about the shares offered by the Server, %%% including hidden shares (those ending with $). %%% Works over the <em>srvsvc</em> pipe. %%% <br/>Example: -%%% <pre> -%%% IpStr = "\\\\192.168.128.51", -%%% Nse = rpc_netr_share_enum(S, Pdu, IpStr), -%%% </pre> +%%% ``` +%%% IpStr = "\\\\192.168.128.51", +%%% Nse = rpc_netr_share_enum(S, Pdu, IpStr), +%%% ''' %%% Where: Nse = [{nse_entry, ?DIR, "NETLOGON", "Logon Server Share"}, ...] %%% @end %%% rpc_netr_share_enum(S, Pdu, IpStr) -> UnicodeP = unicode_p(Pdu), SrvSvcPdu = e_rpc_netr_share_enum(UnicodeP, IpStr), - {ok,RpcRes} = esmb:named_pipe_transaction(S, Pdu, SrvSvcPdu), + {ok,RpcRes,Pdu2} = esmb:named_pipe_transaction(S, Pdu, SrvSvcPdu), case catch d_rpc_response(RpcRes) of NseRes when record(NseRes, rpc_response) -> case catch d_rpc_netr_share_enum(UnicodeP, NseRes) of - {ok, Nse} -> Nse; + {ok, Nse} -> {ok,Nse,Pdu2}; Else -> ?elog("d_netr_share_enum failed: ~p~n",[Else]), throw({error, "netr_share_enum"}) @@ -278,7 +287,7 @@ %%% %%% @spec rpc_samr_connect(S::socket(), PDU::pdu(), %%% IpStr::string()) -> -%%% CtxHandle | exception() +%%% {ok, CtxHandle, pdu()} | exception() %%% %%% @doc The <em>SamrConnect</em> request is the first call that %%% must be made on the <em>samr pipe</em>. @@ -287,11 +296,11 @@ rpc_samr_connect(S, Pdu, IpStr) -> UnicodeP = unicode_p(Pdu), SamrPDU = e_rpc_samr_connect2(UnicodeP, IpStr), - {ok,RpcRes} = esmb:named_pipe_transaction(S, Pdu, SamrPDU), + {ok, RpcRes, Pdu2} = esmb:named_pipe_transaction(S, Pdu, SamrPDU), case catch d_rpc_response(RpcRes) of Resp1 when record(Resp1, rpc_response) -> case catch d_rpc_samr_connect2(UnicodeP, Resp1) of - {ok, CtxHandle} -> CtxHandle; + {ok, CtxHandle} -> {ok, CtxHandle, Pdu2}; {error, Rc} = Err -> throw(Err); Else -> ?elog("d_samr_connect failed: ~p~n",[Else]), @@ -306,7 +315,7 @@ %%% %%% @spec rpc_samr_close(S::socket(), PDU::pdu(), %%% C::ctxHandle()) -> -%%% CtxHandle | throw(Error) +%%% {ok, pdu()} | throw(Error) %%% %%% @doc After any Policy Handles allocated by any SAM Database %%% calls are no longer needed they must be freed with a @@ -315,11 +324,11 @@ %%% rpc_samr_close(S, Pdu, CtxHandle) -> SamrPDU = e_rpc_samr_close(CtxHandle), - {ok,RpcRes} = esmb:named_pipe_transaction(S, Pdu, SamrPDU), + {ok,RpcRes,Pdu2} = esmb:named_pipe_transaction(S, Pdu, SamrPDU), case catch d_rpc_response(RpcRes) of Resp when record(Resp, rpc_response) -> case catch d_rpc_samr_close(Resp) of - ok -> ok; + ok -> {ok, Pdu2}; {error, Rc} = Err -> throw(Err); Else -> ?elog("d_samr_close failed: ~p~n",[Else]), @@ -334,7 +343,7 @@ %%% %%% @spec rpc_samr_enum_doms(S::socket(), PDU::pdu(), %%% C::ctxHandle()) -> -%%% CtxHandle | throw(Error) +%%% {ok, CtxHandle, pdu()} | throw(Error) %%% %%% @doc Obtains a list of Domains at the specified server. %%% @end @@ -342,11 +351,11 @@ rpc_samr_enum_doms(S, Pdu, CtxHandle) -> UnicodeP = unicode_p(Pdu), SamrPDU = e_rpc_samr_enum_doms(UnicodeP, CtxHandle), - {ok,RpcRes} = esmb:named_pipe_transaction(S, Pdu, SamrPDU), + {ok,RpcRes,Pdu2} = esmb:named_pipe_transaction(S, Pdu, SamrPDU), case catch d_rpc_response(RpcRes) of Resp1 when record(Resp1, rpc_response) -> case d_rpc_samr_enum_doms(UnicodeP, Resp1) of - {ok, Doms} -> Doms; + {ok, Doms} -> {ok, Doms, Pdu2}; {error, Rc} = Err -> throw(Err); Else -> ?elog("d_samr_enum_dom failed: ~p~n",[Else]), @@ -361,7 +370,7 @@ %%% %%% @spec rpc_samr_lookup_doms(S::socket(), PDU::pdu(), %%% C::ctxHandle(), D::domains()) -> -%%% domains() | throw(Error) +%%% {ok, domains(), pdu()} | throw(Error) %%% %%% @doc Obtains information about the Domains at the specified server. %%% The information contains the SID (Security Identifier) to be @@ -371,16 +380,15 @@ rpc_samr_lookup_doms(S, Pdu, CtxHandle, Doms) -> UnicodeP = unicode_p(Pdu), Builtin = to_ucs2(UnicodeP, "Builtin"), - X = [D || D <- Doms, - D#dom_entry.domain =/= Builtin], + X = [D || D <- Doms, D#dom_entry.domain =/= Builtin], %% Just one domain at the moment.... Dom = hd(X), SamrPDU = e_rpc_samr_lookup_doms(UnicodeP, CtxHandle, Dom), - {ok,RpcRes} = esmb:named_pipe_transaction(S, Pdu, SamrPDU), + {ok,RpcRes,Pdu2} = esmb:named_pipe_transaction(S, Pdu, SamrPDU), case catch d_rpc_response(RpcRes) of Resp1 when record(Resp1, rpc_response) -> case d_rpc_samr_lookup_doms(UnicodeP, Resp1, Dom) of - {ok, Ds} -> Ds; + {ok, Ds} -> {ok, Ds, Pdu2}; {error, Rc} = Err -> throw(Err); Else -> ?elog("d_samr_lookup_doms failed: ~p~n",[Else]), @@ -395,7 +403,7 @@ %%% @spec rpc_samr_open_domain(S::socket(), PDU::pdu(), %%% IpStr:: string(), C::ctxHandle(), %%% Dom::domain()) -> -%%% ctxHandle() | throw(Error) +%%% {ok, ctxHandle(), pdu()} | throw(Error) %%% %%% @doc Obtains the returned Policy Handle, to be used as input to %%% other Domain operations. @@ -403,11 +411,11 @@ %%% rpc_samr_open_domain(S, Pdu, IpStr, CtxHandle, Domain) -> SamrPDU = e_rpc_samr_open_domain(CtxHandle, Domain), - {ok,RpcRes} = esmb:named_pipe_transaction(S, Pdu, SamrPDU), + {ok,RpcRes,Pdu2} = esmb:named_pipe_transaction(S, Pdu, SamrPDU), case catch d_rpc_response(RpcRes) of Resp1 when record(Resp1, rpc_response) -> case d_rpc_samr_open_domain(Resp1) of - {ok, CtxHandle2} -> CtxHandle2; + {ok, CtxHandle2} -> {ok, CtxHandle2, Pdu2}; {error, Rc} = Err -> throw(Err); Else -> ?elog("d_samr_open_domain failed: ~p~n",[Else]), @@ -423,7 +431,7 @@ %%% @spec rpc_samr_lookup_names(S::socket(), PDU::pdu(), %%% IpStr:: string(), C::ctxHandle(), %%% N::names()) -> -%%% {rid(), ridType()} | throw(Error) +%%% {ok, rid(), ridType(), pdu()} | throw(Error) %%% %%% @doc Resolves User, Group, and Alias names in a Domain to %%% Relative Identifiers (RIDs). The request takes a Domain @@ -433,11 +441,11 @@ %%% rpc_samr_lookup_names(S, Pdu, IpStr, CtxHandle, Names) -> SamrPDU = e_rpc_samr_lookup_names(Pdu, CtxHandle, Names), - {ok,RpcRes} = esmb:named_pipe_transaction(S, Pdu, SamrPDU), + {ok,RpcRes,Pdu2} = esmb:named_pipe_transaction(S, Pdu, SamrPDU), case catch d_rpc_response(RpcRes) of Resp1 when record(Resp1, rpc_response) -> case d_rpc_samr_lookup_names(Resp1) of - {ok, Rid, Type} -> {Rid, Type}; + {ok, Rid, Type} -> {ok, Rid, Type, Pdu2}; {error, Rc} = Err -> throw(Err); Else -> ?elog("d_samr_lookup_names failed: ~p~n",[Else]), @@ -452,8 +460,22 @@ %%% %%% @spec rpc_samr_open_user(S::socket(), PDU::pdu(), %%% IpStr:: string(), C::ctxHandle(), +%%% Name::string(), R::rid()) -> +%%% {ok,ctxHandle(),pdu()} | throw(Error) +%%% +%%% @doc Obtains the returned Policy Handle, to be used as input to +%%% other User operations. +%%% @end +%%% +rpc_samr_open_user(S, Pdu, IpStr, CtxHandle, Name, Rid) -> + User = #name_entry{name = Name, rid = Rid}, + rpc_samr_open_user(S, Pdu, IpStr, CtxHandle, User). + +%%% +%%% @spec rpc_samr_open_user(S::socket(), PDU::pdu(), +%%% IpStr:: string(), C::ctxHandle(), %%% U::user()) -> -%%% ctxHandle() | throw(Error) +%%% {ok,ctxHandle(),pdu()} | throw(Error) %%% %%% @doc Obtains the returned Policy Handle, to be used as input to %%% other User operations. @@ -461,11 +483,11 @@ %%% rpc_samr_open_user(S, Pdu, IpStr, CtxHandle, User) -> SamrPDU = e_rpc_samr_open_user(CtxHandle, User), - {ok,RpcRes} = esmb:named_pipe_transaction(S, Pdu, SamrPDU), + {ok,RpcRes,Pdu2} = esmb:named_pipe_transaction(S, Pdu, SamrPDU), case catch d_rpc_response(RpcRes) of Resp1 when record(Resp1, rpc_response) -> case d_rpc_samr_open_user(Resp1) of - {ok, CtxHandle2} -> CtxHandle2; + {ok, CtxHandle2} -> {ok,CtxHandle2,Pdu2}; {error, Rc} = Err -> throw(Err); Else -> ?elog("d_samr_open_user failed: ~p~n",[Else]), @@ -480,7 +502,7 @@ %%% %%% @spec rpc_samr_user_groups(S::socket(), PDU::pdu(), %%% IpStr:: string(), C::ctxHandle()) -> -%%% nameEntries() | throw(Error) +%%% {ok, nameEntries(), pdu()} | throw(Error) %%% %%% @doc Obtains the RIDs of the groups a certain User belongs to. %%% As input, the Policy Handle returned from an OpenUser @@ -489,11 +511,11 @@ %%% rpc_samr_user_groups(S, Pdu, IpStr, CtxHandle) -> SamrPDU = e_rpc_samr_user_groups(CtxHandle), - {ok,RpcRes} = esmb:named_pipe_transaction(S, Pdu, SamrPDU), + {ok,RpcRes,Pdu2} = esmb:named_pipe_transaction(S, Pdu, SamrPDU), case catch d_rpc_response(RpcRes) of Resp1 when record(Resp1, rpc_response) -> case d_rpc_samr_user_groups(Resp1) of - {ok, RidList} -> RidList; + {ok, RidList} -> {ok,RidList,Pdu2}; {error, Rc} = Err -> throw(Err); Else -> ?elog("d_samr_user_groups failed: ~p~n",[Else]), @@ -509,7 +531,7 @@ %%% @spec rpc_samr_lookup_rids(S::socket(), PDU::pdu(), %%% IpStr:: string(), C::ctxHandle(), %%% nameEntries()) -> -%%% nameEntries() | throw(Error) +%%% {ok, nameEntries(), pdu()} | throw(Error) %%% %%% @doc Resolves User, Group, and Alias names in a Domain, from %%% Relative Identifiers (RIDs). The request takes a Domain @@ -518,11 +540,11 @@ %%% rpc_samr_lookup_rids(S, Pdu, IpStr, CtxHandle, Ns0) -> SamrPDU = e_rpc_samr_lookup_rids(CtxHandle, Ns0), - {ok,RpcRes} = esmb:named_pipe_transaction(S, Pdu, SamrPDU), + {ok,RpcRes,Pdu2} = esmb:named_pipe_transaction(S, Pdu, SamrPDU), case catch d_rpc_response(RpcRes) of Resp1 when record(Resp1, rpc_response) -> case d_rpc_samr_lookup_rids(unicode_p(Pdu), Resp1, Ns0) of - {ok, Ns} -> Ns; + {ok, Ns} -> {ok,Ns,Pdu2}; {error, Rc} = Err -> throw(Err); Else -> ?elog("d_samr_lookup_rids failed: ~p~n",[Else]), @@ -1062,7 +1084,11 @@ ActualCount:32/little, B0/binary>> = Blob, {Share, B1} = str_extract(UnicodeP, ActualCount, B0), - {Comment, Rest} = str_extract(UnicodeP, ActualCount, B0), + <<C_MaxCount:32/little, + C_Offset:32/little, + C_ActualCount:32/little, + B2/binary>> = B1, + {Comment, Rest} = str_extract2(UnicodeP, C_ActualCount, B2), [H#nse_entry{name = Share, comment = Comment} | parse_nse_bodies(UnicodeP, Rest, T)]. @@ -1155,7 +1181,7 @@ ?RPC_OP_BIND_NACK, B/binary>>) -> d_rpc_bind_nack(B); d_bind_response(B) -> - Emsg = "Bind-Response unknown", + Emsg = "DCE/RPC Bind-Response unknown", error_logger:info_msg("~s~n",[Emsg]), {error, Emsg}. @@ -1298,27 +1324,6 @@ -ucs2_to_ascii(Ustr) -> - ucs2_to_charset(Ustr, "ASCII"). - -ucs2_to_charset(Ustr, Cset) -> - case iconv:open(esmb:ucase(Cset), ?CSET_UCS2LE) of - {ok, Cd} -> - case iconv:conv(Cd, Ustr) of - {ok, Res} -> - iconv:close(Cd), - Res; - {error, _Reason} -> - iconv:close(Cd), - Ustr - end; - {error, Reason} -> - ?elog("ucs2_to_charset, open failed Reason=~p , Cset=~p~n", - [Reason, esmb:ucase(Cset)]), - Ustr - end. - - %%% %%% Expect multi-byte chars ? Index: esmb.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/esmb/src/esmb.erl,v retrieving revision 1.18 retrieving revision 1.19 diff -u -d -r1.18 -r1.19 --- esmb.erl 15 Oct 2004 10:44:00 -0000 1.18 +++ esmb.erl 4 Jan 2005 19:19:45 -0000 1.19 @@ -1,38 +1,133 @@ --module(esmb). %%% -------------------------------------------------------------------- %%% File : esmb.erl %%% Created : 10 Dec 2003 by Torbjorn Tornkvist <to...@bl...> -%%% Purpose : Implementation of the NetBIOS/SMB protocol. +%%% +%%% @doc Implementation of the NetBIOS/SMB protocol. +%%% +%%% <p>The <em>esmb</em> library makes it possible to communicate +%%% with SMB servers. In particular Windows servers but also +%%% other implementations of SMB such as [...1697 lines suppressed...] + +%%% @private +ucs2_to_charset(Ustr, Cset) -> + case iconv:open(esmb:ucase(Cset), ?CSET_UCS2LE) of + {ok, Cd} -> + case iconv:conv(Cd, Ustr) of + {ok, Res} -> + iconv:close(Cd), + Res; + {error, _Reason} -> + iconv:close(Cd), + Ustr + end; + {error, Reason} -> + ?elog("ucs2_to_charset, open failed Reason=~p , Cset=~p~n", + [Reason, esmb:ucase(Cset)]), + Ustr + end. + + Index: esmb_lib.hrl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/esmb/src/esmb_lib.hrl,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- esmb_lib.hrl 15 Oct 2004 10:44:00 -0000 1.12 +++ esmb_lib.hrl 4 Jan 2005 19:19:47 -0000 1.13 @@ -128,18 +128,34 @@ -define(DIR_OPEN_OPTIONS, 16#00000001). --define(FLAGS2_LONG_NAMES, 16#0001). --define(FLAGS2_UNICODE, 16#8000). +-define(FLAGS2_SUPPORT_SIGNATURES, 16#0004). +-define(FLAGS2_LONG_NAMES, 16#0001). +-define(FLAGS2_ERR_STATUS, 16#0000). % DOS Error codes +%%%-define(FLAGS2_ERR_STATUS, 16#4000). % NT Error codes +-define(FLAGS2_UNICODE, 16#8000). -define(FLAGS2_NO_UNICODE, 16#7111). -define(FLAGS2_UNSET_UNICODE(X), (X band ?FLAGS2_NO_UNICODE)). -define(FLAGS2_NTLM, (?FLAGS2_LONG_NAMES bor + ?FLAGS2_SUPPORT_SIGNATURES bor ?FLAGS2_UNICODE)). -define(F2_USE_UNICODE(Pdu), ((Pdu#smbpdu.flags2 band ?FLAGS2_UNICODE) > 0)). +%%% Create a new record and copy over important stuff! +-define(CP_PDU(R),(#smbpdu{ + pid = R#smbpdu.pid, + uid = R#smbpdu.uid, + tid = R#smbpdu.tid, + fid = R#smbpdu.fid, + flags2 = R#smbpdu.flags2, + mac_key = R#smbpdu.mac_key, + signatures = R#smbpdu.signatures, + sign_seqno = R#smbpdu.sign_seqno})). + +-define(SIGN_SMB(Pdu), (Pdu#smbpdu.signatures == true)). %%% NB: Multi-byte values must be sent sent with the LSB first !! -record(smbpdu, { @@ -159,7 +175,13 @@ %% --- Own, additional info sub_cmd, % Transaction sub command (if any) fid, % The file ID - file_size % The file size in bytes + file_size, % The file size in bytes + signatures=false, % Enable security signatures of SMB msgs + sign_seqno=0, % Signature request sequence number. + mac_key, % Encryption key used for SMB signing + finfo=[], % List of #file_info{} records + emsg="", % Internal-error msg string + cont % Continuation: F() }). %%% Buffer value-tags @@ -184,15 +206,29 @@ max_buffer_size=?MAX_BUFFER_SIZE }). +%%% SecurityMode flags when LANMAN is negotiated -define(SECMODE_SHARE, 16#0). -define(SECMODE_USER, 16#1). -define(SECMODE_CHALLENGE, 16#2). +%%% SecurityMode flags when NT-LM-0.12 is negotiated +-define(SECMODE_SIGNATURE_ENABLED, 16#4). +-define(SECMODE_SIGNATURE_REQUIRED, 16#8). -define(SCAP_UNICODE, 16#0004). -define(USE_UNICODE(Neg), ((Neg#smb_negotiate_res.srv_capabilities band ?SCAP_UNICODE) > 0)). +-define(USE_ENCRYPTION(Neg), ((Neg#smb_negotiate_res.security_mode + band ?SECMODE_CHALLENGE) > 0) ). + +%%% As soon as the server has 'signatures' enabled we +%%% will sign the SMB PDU's (even though it may not be +%%% required). +-define(USE_SIGNATURES(Neg), + ((Neg#smb_negotiate_res.security_mode band + ?SECMODE_SIGNATURE_ENABLED) > 0)). + %%% Add more dialects when we can support them. %%% Make sure to not break the successive order of %%% the dialects we are sending in the neg-req, so @@ -291,6 +327,7 @@ }). %%% Error class +-define(INTERNAL, -1). % Internal esmb error -define(SUCCESS, 0). % The request was successful -define(ERRDOS, 16#01). % Error is from core DOS OS set -define(ERRSRV, 16#02). % Error generated by srv netw. file manager @@ -298,6 +335,7 @@ -define(ERRCMD, 16#ff). % Command was not in SMB format %%% ERRDOS error codes +%-define(INTERNAL, -1). % same as above... -define(ERRbadfunc, 1). % Invalid function -define(ERRbadfile, 2). % File not found -define(ERRbadpath, 3). % Directory invalid Index: esmb_client.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/esmb/src/esmb_client.erl,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- esmb_client.erl 15 Oct 2004 10:49:06 -0000 1.10 +++ esmb_client.erl 4 Jan 2005 19:19:46 -0000 1.11 @@ -33,6 +33,7 @@ iconv:start(), case host_share(Path) of {Host, Share} -> + io:format("Share=~p~n",[Share]), spawn(fun() -> init(Host, Share, User, Wgroup, Charset) end); Else -> Else @@ -45,11 +46,16 @@ U = #user{pw = Pw, name = User, primary_domain = Wgroup}, Pdu0 = esmb:user_logon(S, Neg, U), esmb:exit_if_error(Pdu0, "Login failed"), - WinPath = mk_winpath(Neg, "//"++Host++"/"++User, Charset), + WinPath = mk_winpath(Neg, "//"++Host++"/"++Share, Charset), Path = to_ucs2(Neg, WinPath, Charset), Pdu1 = esmb:tree_connect(S, Neg, Pdu0, Path), - esmb:exit_if_error(Pdu1, "Tree connect failed"), - shell(S, Neg, {Pdu1, "\\\\"}). + case esmb:error_p(Pdu1) of + false -> + shell(S, Neg, {Pdu1, "\\\\"}); + {true, _Ecode, Emsg} -> + io:format("<ERROR>: ~p~n", [Emsg]), + {error, Emsg} + end. shell(S, Neg, {_Pdu, Cwd} = State) -> @@ -114,12 +120,12 @@ Pdu1 = esmb:open_file_ro(S, Pdu0, Fname), Finfo = #file_info{name = Fname, size = Pdu1#smbpdu.file_size}, io:format("Reading....~n", []), - {Time, {ok, Bin}} = timer:tc(esmb, read_file, [S, Pdu1, Finfo]), + {Time, {ok, Bin, Pdu2}} = timer:tc(esmb, read_file, [S, Pdu1, Finfo]), Size = size(Bin), io:format("Read ~p bytes (~p bytes/sec)~n", [Size, Size/(Time/1000000)]), Fun(Bin, File), - Pdu = esmb:close_file(S, Pdu1), + Pdu = esmb:close_file(S, Pdu2, Pdu1#smbpdu.fid), {Pdu, Cwd}. @@ -132,10 +138,10 @@ Pdu1 = esmb:open_file_rw(S, Pdu0, Fname), Finfo = #file_info{name = Fname, data = [Bin]}, io:format("Writing....~n", []), - {Time,Res} = timer:tc(esmb, write_file, [S, Neg, Pdu1, Finfo]), - io:format("Wrote ~p bytes/sec, res=~p~n", - [size(Bin)/(Time/1000000), Res]), - Pdu = esmb:close_file(S, Pdu1), + {Time, {ok, Wrote, Pdu2}} = timer:tc(esmb, write_file, [S, Neg, Pdu1, Finfo]), + io:format("Wrote ~p bytes/sec~n", + [size(Bin)/(Time/1000000)]), + Pdu = esmb:close_file(S, Pdu2, Pdu1#smbpdu.fid), {Pdu, Cwd}. @@ -145,7 +151,7 @@ WinPath = mk_winpath(Neg, Cwd ++ slash(Cset) ++ File, Cset), Fname = to_ucs2(Neg, WinPath, Cset), Pdu1 = esmb:mkdir(S, Pdu0, Fname), - Pdu = esmb:close_file(S, Pdu1), + Pdu = esmb:close_file(S, Pdu1, Pdu1#smbpdu.fid), {Pdu, Cwd}. rmdir(S, Neg, {Pdu0, Cwd}, Dir0) -> @@ -169,8 +175,8 @@ Cset = get(charset), WinPath = mk_winpath(Neg, Cwd, Cset), Udir = to_ucs2(Neg, add_wildcard(Neg, Cset, WinPath), Cset), - Finfo = esmb:list_dir(S, Pdu, Udir), - print_file_info(Neg, Finfo), + Rpdu = esmb:list_dir(S, Pdu, Udir), + print_file_info(Neg, Rpdu#smbpdu.finfo), State. print_file_info(Neg, L) -> @@ -228,9 +234,10 @@ host_share([$\s|T]) -> host_share(T); host_share("//" ++ T) -> - {Host, Share} = eat_until(T, $/), + {Host, "/" ++ Share} = eat_until(T, $/), {Host, Share}. + eat_until(Cs, X) -> eat_until(Cs, X, []). @@ -425,8 +432,8 @@ Fname = to_ucs2(Neg, WinPath, Cset), Pdu1 = esmb:open_file_ro(S, Pdu0, Fname), Finfo = #file_info{name = Fname, size = Pdu1#smbpdu.file_size}, - {ok, Bin} = esmb:read_file(S, Pdu1, Finfo), + {ok, Bin, Pdu2} = esmb:read_file(S, Pdu1, Finfo), Fun(Bin, File), - Pdu = esmb:close_file(S, Pdu1), + esmb:close_file(S, Pdu2), {ok, size(Bin)}. -endif. |