2 Unix SMB/CIFS implementation.
4 dcerpc over SMB transport
6 Copyright (C) Tim Potter 2003
7 Copyright (C) Andrew Tridgell 2003
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "system/filesys.h"
26 #include "lib/tsocket/tsocket.h"
27 #include "libcli/smb/smb_constants.h"
28 #include "libcli/smb/smbXcli_base.h"
29 #include "libcli/smb/tstream_smbXcli_np.h"
30 #include "libcli/raw/libcliraw.h"
31 #include "libcli/smb2/smb2.h"
32 #include "librpc/rpc/dcerpc.h"
33 #include "librpc/rpc/dcerpc_proto.h"
34 #include "libcli/composite/composite.h"
36 /* transport private information used by SMB pipe transport */
38 DATA_BLOB session_key
;
41 * these are needed to open a secondary connection
43 struct smbXcli_conn
*conn
;
44 struct smbXcli_session
*session
;
45 struct smbXcli_tcon
*tcon
;
46 uint32_t timeout_msec
;
50 fetch the user session key
52 static NTSTATUS
smb_session_key(struct dcecli_connection
*c
, DATA_BLOB
*session_key
)
54 struct smb_private
*smb
= talloc_get_type_abort(
55 c
->transport
.private_data
, struct smb_private
);
57 if (smb
== NULL
) return NT_STATUS_CONNECTION_DISCONNECTED
;
59 if (smb
->session_key
.length
== 0) {
60 return NT_STATUS_NO_USER_SESSION_KEY
;
63 *session_key
= smb
->session_key
;
67 struct dcerpc_pipe_open_smb_state
{
68 struct dcecli_connection
*c
;
69 struct composite_context
*ctx
;
73 struct smb_private
*smb
;
76 static void dcerpc_pipe_open_smb_done(struct tevent_req
*subreq
);
78 struct composite_context
*dcerpc_pipe_open_smb_send(struct dcecli_connection
*c
,
79 struct smbXcli_conn
*conn
,
80 struct smbXcli_session
*session
,
81 struct smbXcli_tcon
*tcon
,
82 uint32_t timeout_msec
,
83 const char *pipe_name
)
85 struct composite_context
*ctx
;
86 struct dcerpc_pipe_open_smb_state
*state
;
88 struct tevent_req
*subreq
;
90 ctx
= composite_create(c
, c
->event_ctx
);
91 if (ctx
== NULL
) return NULL
;
93 state
= talloc(ctx
, struct dcerpc_pipe_open_smb_state
);
94 if (composite_nomem(state
, ctx
)) return ctx
;
95 ctx
->private_data
= state
;
100 if ((strncasecmp(pipe_name
, "/pipe/", 6) == 0) ||
101 (strncasecmp(pipe_name
, "\\pipe\\", 6) == 0)) {
104 if ((strncasecmp(pipe_name
, "/", 1) == 0) ||
105 (strncasecmp(pipe_name
, "\\", 1) == 0)) {
108 state
->fname
= talloc_strdup(state
, pipe_name
);
109 if (composite_nomem(state
->fname
, ctx
)) return ctx
;
111 state
->smb
= talloc_zero(state
, struct smb_private
);
112 if (composite_nomem(state
->smb
, ctx
)) return ctx
;
114 state
->smb
->conn
= conn
;
115 state
->smb
->session
= session
;
116 state
->smb
->tcon
= tcon
;
117 state
->smb
->timeout_msec
= timeout_msec
;
119 state
->c
->server_name
= strupper_talloc(state
->c
,
120 smbXcli_conn_remote_name(conn
));
121 if (composite_nomem(state
->c
->server_name
, ctx
)) return ctx
;
123 ctx
->status
= smbXcli_session_application_key(session
,
125 &state
->smb
->session_key
);
126 if (NT_STATUS_EQUAL(ctx
->status
, NT_STATUS_NO_USER_SESSION_KEY
)) {
127 state
->smb
->session_key
= data_blob_null
;
128 ctx
->status
= NT_STATUS_OK
;
130 if (!composite_is_ok(ctx
)) return ctx
;
132 subreq
= tstream_smbXcli_np_open_send(state
, c
->event_ctx
,
133 conn
, session
, tcon
, pid
,
134 timeout_msec
, state
->fname
);
135 if (composite_nomem(subreq
, ctx
)) return ctx
;
136 tevent_req_set_callback(subreq
, dcerpc_pipe_open_smb_done
, state
);
141 static void dcerpc_pipe_open_smb_done(struct tevent_req
*subreq
)
143 struct dcerpc_pipe_open_smb_state
*state
=
144 tevent_req_callback_data(subreq
,
145 struct dcerpc_pipe_open_smb_state
);
146 struct composite_context
*ctx
= state
->ctx
;
147 struct dcecli_connection
*c
= state
->c
;
149 ctx
->status
= tstream_smbXcli_np_open_recv(subreq
,
151 &state
->c
->transport
.stream
);
153 if (!composite_is_ok(ctx
)) return;
155 state
->c
->transport
.write_queue
=
156 tevent_queue_create(state
->c
, "dcerpc_smb write queue");
157 if (composite_nomem(state
->c
->transport
.write_queue
, ctx
)) return;
160 fill in the transport methods
162 c
->transport
.transport
= NCACN_NP
;
163 c
->transport
.private_data
= NULL
;
166 * Windows uses 4280 for ncacn_np,
167 * so we also use it, this is what our
168 * tstream_smbXcli_np code relies on.
170 c
->srv_max_xmit_frag
= 4280;
171 c
->srv_max_recv_frag
= 4280;
173 /* Over-ride the default session key with the SMB session key */
174 c
->security_state
.session_key
= smb_session_key
;
176 c
->transport
.private_data
= talloc_move(c
, &state
->smb
);
181 NTSTATUS
dcerpc_pipe_open_smb_recv(struct composite_context
*c
)
183 NTSTATUS status
= composite_wait(c
);
188 _PUBLIC_ NTSTATUS
dcerpc_pipe_open_smb(struct dcerpc_pipe
*p
,
189 struct smbcli_tree
*t
,
190 const char *pipe_name
)
192 struct smbXcli_conn
*conn
;
193 struct smbXcli_session
*session
;
194 struct smbXcli_tcon
*tcon
;
195 uint32_t timeout_msec
;
196 struct composite_context
*ctx
;
198 conn
= t
->session
->transport
->conn
;
199 session
= t
->session
->smbXcli
;
201 smb1cli_tcon_set_id(tcon
, t
->tid
);
202 timeout_msec
= t
->session
->transport
->options
.request_timeout
* 1000;
204 /* if we don't have a binding on this pipe yet, then create one */
205 if (p
->binding
== NULL
) {
206 struct dcerpc_binding
*b
;
208 const char *r
= smbXcli_conn_remote_name(conn
);
210 SMB_ASSERT(r
!= NULL
);
211 str
= talloc_asprintf(p
, "ncacn_np:%s", r
);
213 return NT_STATUS_NO_MEMORY
;
215 status
= dcerpc_parse_binding(p
, str
, &b
);
217 if (!NT_STATUS_IS_OK(status
)) {
223 ctx
= dcerpc_pipe_open_smb_send(p
->conn
,
228 return NT_STATUS_NO_MEMORY
;
231 return dcerpc_pipe_open_smb_recv(ctx
);
234 _PUBLIC_ NTSTATUS
dcerpc_pipe_open_smb2(struct dcerpc_pipe
*p
,
236 const char *pipe_name
)
238 struct smbXcli_conn
*conn
;
239 struct smbXcli_session
*session
;
240 struct smbXcli_tcon
*tcon
;
241 uint32_t timeout_msec
;
242 struct composite_context
*ctx
;
244 conn
= t
->session
->transport
->conn
;
245 session
= t
->session
->smbXcli
;
247 timeout_msec
= t
->session
->transport
->options
.request_timeout
* 1000;
249 /* if we don't have a binding on this pipe yet, then create one */
250 if (p
->binding
== NULL
) {
251 struct dcerpc_binding
*b
;
253 const char *r
= smbXcli_conn_remote_name(conn
);
255 SMB_ASSERT(r
!= NULL
);
256 str
= talloc_asprintf(p
, "ncacn_np:%s", r
);
258 return NT_STATUS_NO_MEMORY
;
260 status
= dcerpc_parse_binding(p
, str
, &b
);
262 if (!NT_STATUS_IS_OK(status
)) {
268 ctx
= dcerpc_pipe_open_smb_send(p
->conn
,
273 return NT_STATUS_NO_MEMORY
;
276 return dcerpc_pipe_open_smb_recv(ctx
);
279 struct composite_context
*dcerpc_secondary_smb_send(struct dcecli_connection
*c1
,
280 struct dcecli_connection
*c2
,
281 const char *pipe_name
)
283 struct smb_private
*smb
;
285 if (c1
->transport
.transport
!= NCACN_NP
) return NULL
;
287 smb
= talloc_get_type(c1
->transport
.private_data
, struct smb_private
);
288 if (!smb
) return NULL
;
290 return dcerpc_pipe_open_smb_send(c2
,
298 NTSTATUS
dcerpc_secondary_smb_recv(struct composite_context
*c
)
300 return dcerpc_pipe_open_smb_recv(c
);