2 Unix SMB/CIFS implementation.
3 service (connection) opening and closing
4 Copyright (C) Andrew Tridgell 1992-1998
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 "system/filesys.h"
22 #include "system/passwd.h" /* uid_wrapper */
23 #include "../lib/tsocket/tsocket.h"
24 #include "smbd/smbd.h"
25 #include "smbd/globals.h"
26 #include "../librpc/gen_ndr/netlogon.h"
27 #include "../libcli/security/security.h"
28 #include "printing/pcap.h"
29 #include "passdb/lookup_sid.h"
31 #include "../auth/auth_util.h"
32 #include "lib/param/loadparm.h"
34 #include "lib/afs/afs_funcs.h"
35 #include "lib/util_path.h"
36 #include "lib/util/string_wrappers.h"
37 #include "source3/lib/substitute.h"
39 /****************************************************************************
40 Make a connection to a service from SMB1. Internal interface.
41 ****************************************************************************/
43 static connection_struct
*make_connection_smb1(struct smb_request
*req
,
49 const struct loadparm_substitution
*lp_sub
=
50 loadparm_s3_global_substitution();
51 struct smbXsrv_tcon
*tcon
;
53 struct connection_struct
*conn
;
55 status
= smb1srv_tcon_create(req
->xconn
, now
, &tcon
);
56 if (!NT_STATUS_IS_OK(status
)) {
57 DEBUG(0,("make_connection_smb1: Couldn't find free tcon %s.\n",
63 conn
= conn_new(req
->sconn
);
67 DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
68 *pstatus
= NT_STATUS_INSUFFICIENT_RESOURCES
;
72 conn
->cnum
= tcon
->global
->tcon_wire_id
;
75 *pstatus
= make_connection_snum(req
->xconn
,
80 if (!NT_STATUS_IS_OK(*pstatus
)) {
86 tcon
->global
->share_name
= lp_servicename(tcon
->global
, lp_sub
, SNUM(conn
));
87 if (tcon
->global
->share_name
== NULL
) {
90 *pstatus
= NT_STATUS_NO_MEMORY
;
93 tcon
->global
->session_global_id
=
94 req
->session
->global
->session_global_id
;
96 tcon
->compat
= talloc_move(tcon
, &conn
);
97 tcon
->status
= NT_STATUS_OK
;
99 *pstatus
= smbXsrv_tcon_update(tcon
);
100 if (!NT_STATUS_IS_OK(*pstatus
)) {
108 /****************************************************************************
109 Make a connection to a service. External SMB1 interface.
112 ****************************************************************************/
114 connection_struct
*make_connection(struct smb_request
*req
,
116 const char *service_in
,
117 const char *pdev
, uint64_t vuid
,
120 struct smbd_server_connection
*sconn
= req
->sconn
;
121 struct smbXsrv_session
*session
= req
->session
;
122 const struct loadparm_substitution
*lp_sub
=
123 loadparm_s3_global_substitution();
125 char *service
= NULL
;
131 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
133 if (!non_root_mode() && (euid
= geteuid()) != 0) {
134 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
135 "(%u)\n", (unsigned int)euid
));
136 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
139 if (conn_num_open(sconn
) > 2047) {
140 *status
= NT_STATUS_INSUFF_SERVER_RESOURCES
;
144 if (session
== NULL
) {
145 DEBUG(1,("make_connection: refusing to connect with "
146 "no session setup\n"));
147 *status
= NT_STATUS_ACCESS_DENIED
;
151 /* Logic to try and connect to the correct [homes] share, preferably
152 without too many getpwnam() lookups. This is particulary nasty for
153 winbind usernames, where the share name isn't the same as unix
157 if (strequal(service_in
,HOMES_NAME
)) {
158 if (session
->homes_snum
== -1) {
159 DEBUG(2, ("[homes] share not available for "
160 "this user because it was not found "
161 "or created at session setup "
163 *status
= NT_STATUS_BAD_NETWORK_NAME
;
166 DEBUG(5, ("making a connection to [homes] service "
167 "created at session setup time\n"));
168 return make_connection_smb1(req
, now
,
171 } else if ((session
->homes_snum
!= -1)
172 && strequal(service_in
,
173 lp_const_servicename(session
->homes_snum
))) {
174 DEBUG(5, ("making a connection to 'homes' service [%s] "
175 "created at session setup time\n", service_in
));
176 return make_connection_smb1(req
, now
,
181 service
= talloc_strdup(talloc_tos(), service_in
);
183 *status
= NT_STATUS_NO_MEMORY
;
187 if (!strlower_m(service
)) {
188 DEBUG(2, ("strlower_m %s failed\n", service
));
189 *status
= NT_STATUS_INVALID_PARAMETER
;
193 snum
= find_service(talloc_tos(), service
, &service
);
195 *status
= NT_STATUS_NO_MEMORY
;
200 if (strequal(service
,"IPC$") ||
201 (lp_enable_asu_support() && strequal(service
,"ADMIN$"))) {
202 DEBUG(3,("refusing IPC connection to %s\n", service
));
203 *status
= NT_STATUS_ACCESS_DENIED
;
207 DEBUG(3,("%s (%s) couldn't find service %s\n",
208 get_remote_machine_name(),
209 tsocket_address_string(
210 sconn
->remote_address
, talloc_tos()),
212 *status
= NT_STATUS_BAD_NETWORK_NAME
;
216 /* Handle non-Dfs clients attempting connections to msdfs proxy */
217 if (lp_host_msdfs() && (*lp_msdfs_proxy(talloc_tos(), lp_sub
, snum
) != '\0')) {
218 DEBUG(3, ("refusing connection to dfs proxy share '%s' "
219 "(pointing to %s)\n",
220 service
, lp_msdfs_proxy(talloc_tos(), lp_sub
, snum
)));
221 *status
= NT_STATUS_BAD_NETWORK_NAME
;
225 DEBUG(5, ("making a connection to 'normal' service %s\n", service
));
227 return make_connection_smb1(req
, now
, snum
,