Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : service (connection) opening and closing
4 : Copyright (C) Andrew Tridgell 1992-1998
5 :
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.
10 :
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.
15 :
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/>.
18 : */
19 :
20 : #include "includes.h"
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"
30 : #include "auth.h"
31 : #include "../auth/auth_util.h"
32 : #include "lib/param/loadparm.h"
33 : #include "messages.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"
38 :
39 : /****************************************************************************
40 : Make a connection to a service from SMB1. Internal interface.
41 : ****************************************************************************/
42 :
43 9303 : static connection_struct *make_connection_smb1(struct smb_request *req,
44 : NTTIME now,
45 : int snum,
46 : const char *pdev,
47 : NTSTATUS *pstatus)
48 : {
49 144 : const struct loadparm_substitution *lp_sub =
50 9303 : loadparm_s3_global_substitution();
51 144 : uint32_t session_global_id;
52 9303 : char *share_name = NULL;
53 144 : struct smbXsrv_tcon *tcon;
54 144 : NTSTATUS status;
55 144 : struct connection_struct *conn;
56 :
57 9303 : session_global_id = req->session->global->session_global_id;
58 9303 : share_name = lp_servicename(talloc_tos(), lp_sub, snum);
59 9303 : if (share_name == NULL) {
60 0 : *pstatus = NT_STATUS_NO_MEMORY;
61 0 : return NULL;
62 : }
63 :
64 9303 : if ((lp_max_connections(snum) > 0)
65 0 : && (count_current_connections(lp_const_servicename(snum), true) >=
66 0 : lp_max_connections(snum))) {
67 :
68 0 : DBG_WARNING("Max connections (%d) exceeded for [%s][%s]\n",
69 : lp_max_connections(snum),
70 : lp_const_servicename(snum), share_name);
71 0 : TALLOC_FREE(share_name);
72 0 : *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
73 0 : return NULL;
74 : }
75 :
76 9303 : status = smb1srv_tcon_create(req->xconn,
77 : session_global_id,
78 : share_name,
79 : now, &tcon);
80 9303 : if (!NT_STATUS_IS_OK(status)) {
81 0 : DEBUG(0,("make_connection_smb1: Couldn't find free tcon for [%s] - %s\n",
82 : share_name, nt_errstr(status)));
83 0 : TALLOC_FREE(share_name);
84 0 : *pstatus = status;
85 0 : return NULL;
86 : }
87 9303 : TALLOC_FREE(share_name);
88 :
89 9303 : conn = conn_new(req->sconn);
90 9303 : if (!conn) {
91 0 : TALLOC_FREE(tcon);
92 :
93 0 : DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
94 0 : *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
95 0 : return NULL;
96 : }
97 :
98 9303 : conn->cnum = tcon->global->tcon_wire_id;
99 9303 : conn->tcon = tcon;
100 :
101 9303 : *pstatus = make_connection_snum(req->xconn,
102 : conn,
103 : snum,
104 : req->session,
105 : pdev);
106 9303 : if (!NT_STATUS_IS_OK(*pstatus)) {
107 58 : conn_free(conn);
108 58 : TALLOC_FREE(tcon);
109 58 : return NULL;
110 : }
111 :
112 9245 : tcon->compat = talloc_move(tcon, &conn);
113 9245 : tcon->status = NT_STATUS_OK;
114 :
115 9245 : *pstatus = NT_STATUS_OK;
116 :
117 9245 : return tcon->compat;
118 : }
119 :
120 : /****************************************************************************
121 : Make a connection to a service. External SMB1 interface.
122 : *
123 : * @param service
124 : ****************************************************************************/
125 :
126 9313 : connection_struct *make_connection(struct smb_request *req,
127 : NTTIME now,
128 : const char *service_in,
129 : const char *pdev, uint64_t vuid,
130 : NTSTATUS *status)
131 : {
132 9313 : struct smbd_server_connection *sconn = req->sconn;
133 9313 : struct smbXsrv_session *session = req->session;
134 144 : const struct loadparm_substitution *lp_sub =
135 9313 : loadparm_s3_global_substitution();
136 144 : uid_t euid;
137 9313 : char *service = NULL;
138 144 : fstring dev;
139 9313 : int snum = -1;
140 :
141 9313 : fstrcpy(dev, pdev);
142 :
143 : /* This must ONLY BE CALLED AS ROOT. As it exits this function as
144 : * root. */
145 9313 : if (!non_root_mode() && (euid = geteuid()) != 0) {
146 0 : DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
147 : "(%u)\n", (unsigned int)euid ));
148 0 : smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
149 : }
150 :
151 9313 : if (conn_num_open(sconn) > 2047) {
152 0 : *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
153 0 : return NULL;
154 : }
155 :
156 9313 : if (session == NULL) {
157 2 : DEBUG(1,("make_connection: refusing to connect with "
158 : "no session setup\n"));
159 2 : *status = NT_STATUS_ACCESS_DENIED;
160 2 : return NULL;
161 : }
162 :
163 : /* Logic to try and connect to the correct [homes] share, preferably
164 : without too many getpwnam() lookups. This is particularly nasty for
165 : winbind usernames, where the share name isn't the same as unix
166 : username.
167 : */
168 :
169 9311 : if (strequal(service_in,HOMES_NAME)) {
170 0 : if (session->homes_snum == -1) {
171 0 : DEBUG(2, ("[homes] share not available for "
172 : "this user because it was not found "
173 : "or created at session setup "
174 : "time\n"));
175 0 : *status = NT_STATUS_BAD_NETWORK_NAME;
176 0 : return NULL;
177 : }
178 0 : DEBUG(5, ("making a connection to [homes] service "
179 : "created at session setup time\n"));
180 0 : return make_connection_smb1(req, now,
181 0 : session->homes_snum,
182 : dev, status);
183 9311 : } else if ((session->homes_snum != -1)
184 5902 : && strequal(service_in,
185 5902 : lp_const_servicename(session->homes_snum))) {
186 0 : DEBUG(5, ("making a connection to 'homes' service [%s] "
187 : "created at session setup time\n", service_in));
188 0 : return make_connection_smb1(req, now,
189 0 : session->homes_snum,
190 : dev, status);
191 : }
192 :
193 9311 : service = talloc_strdup(talloc_tos(), service_in);
194 9311 : if (!service) {
195 0 : *status = NT_STATUS_NO_MEMORY;
196 0 : return NULL;
197 : }
198 :
199 9311 : if (!strlower_m(service)) {
200 0 : DEBUG(2, ("strlower_m %s failed\n", service));
201 0 : *status = NT_STATUS_INVALID_PARAMETER;
202 0 : return NULL;
203 : }
204 :
205 9311 : snum = find_service(talloc_tos(), service, &service);
206 9311 : if (!service) {
207 0 : *status = NT_STATUS_NO_MEMORY;
208 0 : return NULL;
209 : }
210 :
211 9311 : if (snum < 0) {
212 16 : if (strequal(service,"IPC$") ||
213 8 : (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
214 0 : DEBUG(3,("refusing IPC connection to %s\n", service));
215 0 : *status = NT_STATUS_ACCESS_DENIED;
216 0 : return NULL;
217 : }
218 :
219 8 : DEBUG(3,("%s (%s) couldn't find service %s\n",
220 : get_remote_machine_name(),
221 : tsocket_address_string(
222 : sconn->remote_address, talloc_tos()),
223 : service));
224 8 : *status = NT_STATUS_BAD_NETWORK_NAME;
225 8 : return NULL;
226 : }
227 :
228 : /* Handle non-Dfs clients attempting connections to msdfs proxy */
229 9303 : if (lp_host_msdfs() && (*lp_msdfs_proxy(talloc_tos(), lp_sub, snum) != '\0')) {
230 0 : DEBUG(3, ("refusing connection to dfs proxy share '%s' "
231 : "(pointing to %s)\n",
232 : service, lp_msdfs_proxy(talloc_tos(), lp_sub, snum)));
233 0 : *status = NT_STATUS_BAD_NETWORK_NAME;
234 0 : return NULL;
235 : }
236 :
237 9303 : DEBUG(5, ("making a connection to 'normal' service %s\n", service));
238 :
239 9303 : return make_connection_smb1(req, now, snum,
240 : dev, status);
241 : }
|