2 Unix SMB/CIFS implementation.
3 service (connection) handling
4 Copyright (C) Andrew Tridgell 1992-2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "smb_server/smb_server.h"
22 #include "smbd/service_stream.h"
23 #include "ntvfs/ntvfs.h"
24 #include "param/param.h"
26 /****************************************************************************
27 Make a connection, given the snum to connect to, and the vuser of the
28 connecting user if appropriate.
29 Does note invoke the NTVFS connection hook
30 ****************************************************************************/
31 static NTSTATUS
make_connection_scfg(struct smbsrv_request
*req
,
32 struct share_config
*scfg
,
37 struct smbsrv_tcon
*tcon
;
39 uint64_t ntvfs_caps
= 0;
41 tcon
= smbsrv_smb_tcon_new(req
->smb_conn
, scfg
->name
);
43 DEBUG(0,("Couldn't find free connection.\n"));
44 return NT_STATUS_INSUFFICIENT_RESOURCES
;
48 if (req
->smb_conn
->negotiate
.client_caps
& CAP_LEVEL_II_OPLOCKS
) {
49 ntvfs_caps
|= NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS
;
52 /* init ntvfs function pointers */
53 status
= ntvfs_init_connection(tcon
, scfg
, type
,
54 req
->smb_conn
->negotiate
.protocol
,
56 req
->smb_conn
->connection
->event
.ctx
,
57 req
->smb_conn
->connection
->msg_ctx
,
58 req
->smb_conn
->lp_ctx
,
59 req
->smb_conn
->connection
->server_id
,
61 if (!NT_STATUS_IS_OK(status
)) {
62 DEBUG(0, ("make_connection_scfg: connection failed for service %s\n",
67 status
= ntvfs_set_oplock_handler(tcon
->ntvfs
, smbsrv_send_oplock_break
, tcon
);
68 if (!NT_STATUS_IS_OK(status
)) {
69 DEBUG(0,("make_connection: NTVFS failed to set the oplock handler!\n"));
73 status
= ntvfs_set_addresses(tcon
->ntvfs
,
74 req
->smb_conn
->connection
->local_address
,
75 req
->smb_conn
->connection
->remote_address
);
76 if (!NT_STATUS_IS_OK(status
)) {
77 DEBUG(0,("make_connection: NTVFS failed to set the addresses!\n"));
81 status
= ntvfs_set_handle_callbacks(tcon
->ntvfs
,
82 smbsrv_handle_create_new
,
83 smbsrv_handle_make_valid
,
84 smbsrv_handle_destroy
,
85 smbsrv_handle_search_by_wire_key
,
86 smbsrv_handle_get_wire_key
,
88 if (!NT_STATUS_IS_OK(status
)) {
89 DEBUG(0,("make_connection: NTVFS failed to set the handle callbacks!\n"));
101 /****************************************************************************
102 Make a connection to a service.
105 ****************************************************************************/
106 static NTSTATUS
make_connection(struct smbsrv_request
*req
,
107 const char *service
, DATA_BLOB password
,
111 enum ntvfs_type type
;
112 const char *type_str
;
113 struct share_config
*scfg
;
114 const char *sharetype
;
116 /* the service might be of the form \\SERVER\SHARE. Should we put
117 the server name we get from this somewhere? */
118 if (strncmp(service
, "\\\\", 2) == 0) {
119 char *p
= strchr(service
+2, '\\');
125 status
= share_get_config(req
, req
->smb_conn
->share_context
, service
, &scfg
);
126 if (!NT_STATUS_IS_OK(status
)) {
127 DEBUG(0,("make_connection: couldn't find service %s\n", service
));
128 return NT_STATUS_BAD_NETWORK_NAME
;
131 /* TODO: check the password, when it's share level security! */
133 if (!socket_check_access(req
->smb_conn
->connection
->socket
,
135 share_string_list_option(req
, scfg
, SHARE_HOSTS_ALLOW
),
136 share_string_list_option(req
, scfg
, SHARE_HOSTS_DENY
))) {
137 return NT_STATUS_ACCESS_DENIED
;
140 /* work out what sort of connection this is */
141 sharetype
= share_string_option(scfg
, "type", "DISK");
142 if (sharetype
&& strcmp(sharetype
, "IPC") == 0) {
145 } else if (sharetype
&& strcmp(sharetype
, "PRINTER") == 0) {
153 if (strcmp(dev
, "?????") != 0 && strcasecmp(type_str
, dev
) != 0) {
154 /* the client gave us the wrong device type */
155 return NT_STATUS_BAD_DEVICE_TYPE
;
158 return make_connection_scfg(req
, scfg
, type
, password
, dev
);
162 backend for tree connect call, in preparation for calling ntvfs_connect()
164 NTSTATUS
smbsrv_tcon_backend(struct smbsrv_request
*req
, union smb_tcon
*con
)
168 if (con
->generic
.level
== RAW_TCON_TCON
) {
170 password
= data_blob_string_const(con
->tcon
.in
.password
);
172 status
= make_connection(req
, con
->tcon
.in
.service
, password
, con
->tcon
.in
.dev
);
174 if (!NT_STATUS_IS_OK(status
)) {
178 con
->tcon
.out
.max_xmit
= req
->smb_conn
->negotiate
.max_recv
;
179 con
->tcon
.out
.tid
= req
->tcon
->tid
;
184 /* TODO: take a look at tconx.in.flags! */
186 status
= make_connection(req
, con
->tconx
.in
.path
, con
->tconx
.in
.password
,
187 con
->tconx
.in
.device
);
188 if (!NT_STATUS_IS_OK(status
)) {
192 con
->tconx
.out
.tid
= req
->tcon
->tid
;
193 con
->tconx
.out
.options
= SMB_SUPPORT_SEARCH_BITS
| (share_int_option(req
->tcon
->ntvfs
->config
, SHARE_CSC_POLICY
, SHARE_CSC_POLICY_DEFAULT
) << 2);
194 if (share_bool_option(req
->tcon
->ntvfs
->config
, SHARE_MSDFS_ROOT
, SHARE_MSDFS_ROOT_DEFAULT
) && lpcfg_host_msdfs(req
->smb_conn
->lp_ctx
)) {
195 con
->tconx
.out
.options
|= SMB_SHARE_IN_DFS
;