ctdb/docs: Include ceph rados namespace support in man page
[Samba.git] / source3 / smbd / smb1_service.c
blob99541010c40d1a27f26871f3133085cc8a4f27d1
1 /*
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/>.
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"
39 /****************************************************************************
40 Make a connection to a service from SMB1. Internal interface.
41 ****************************************************************************/
43 static connection_struct *make_connection_smb1(struct smb_request *req,
44 NTTIME now,
45 int snum,
46 const char *pdev,
47 NTSTATUS *pstatus)
49 const struct loadparm_substitution *lp_sub =
50 loadparm_s3_global_substitution();
51 uint32_t session_global_id;
52 char *share_name = NULL;
53 struct smbXsrv_tcon *tcon;
54 NTSTATUS status;
55 struct connection_struct *conn;
57 session_global_id = req->session->global->session_global_id;
58 share_name = lp_servicename(talloc_tos(), lp_sub, snum);
59 if (share_name == NULL) {
60 *pstatus = NT_STATUS_NO_MEMORY;
61 return NULL;
64 if ((lp_max_connections(snum) > 0)
65 && (count_current_connections(lp_const_servicename(snum), true) >=
66 lp_max_connections(snum))) {
68 DBG_WARNING("Max connections (%d) exceeded for [%s][%s]\n",
69 lp_max_connections(snum),
70 lp_const_servicename(snum), share_name);
71 TALLOC_FREE(share_name);
72 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
73 return NULL;
76 status = smb1srv_tcon_create(req->xconn,
77 session_global_id,
78 share_name,
79 now, &tcon);
80 if (!NT_STATUS_IS_OK(status)) {
81 DEBUG(0,("make_connection_smb1: Couldn't find free tcon for [%s] - %s\n",
82 share_name, nt_errstr(status)));
83 TALLOC_FREE(share_name);
84 *pstatus = status;
85 return NULL;
87 TALLOC_FREE(share_name);
89 conn = conn_new(req->sconn);
90 if (!conn) {
91 TALLOC_FREE(tcon);
93 DEBUG(0,("make_connection_smb1: Couldn't find free connection.\n"));
94 *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
95 return NULL;
98 conn->cnum = tcon->global->tcon_wire_id;
99 conn->tcon = tcon;
101 *pstatus = make_connection_snum(req->xconn,
102 conn,
103 snum,
104 req->session,
105 pdev);
106 if (!NT_STATUS_IS_OK(*pstatus)) {
107 conn_free(conn);
108 TALLOC_FREE(tcon);
109 return NULL;
112 tcon->compat = talloc_move(tcon, &conn);
113 tcon->status = NT_STATUS_OK;
115 *pstatus = NT_STATUS_OK;
117 return tcon->compat;
120 /****************************************************************************
121 Make a connection to a service. External SMB1 interface.
123 * @param service
124 ****************************************************************************/
126 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)
132 struct smbd_server_connection *sconn = req->sconn;
133 struct smbXsrv_session *session = req->session;
134 const struct loadparm_substitution *lp_sub =
135 loadparm_s3_global_substitution();
136 uid_t euid;
137 char *service = NULL;
138 fstring dev;
139 int snum = -1;
141 fstrcpy(dev, pdev);
143 /* This must ONLY BE CALLED AS ROOT. As it exits this function as
144 * root. */
145 if (!non_root_mode() && (euid = geteuid()) != 0) {
146 DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot "
147 "(%u)\n", (unsigned int)euid ));
148 smb_panic("make_connection: PANIC ERROR. Called as nonroot\n");
151 if (conn_num_open(sconn) > 2047) {
152 *status = NT_STATUS_INSUFF_SERVER_RESOURCES;
153 return NULL;
156 if (session == NULL) {
157 DEBUG(1,("make_connection: refusing to connect with "
158 "no session setup\n"));
159 *status = NT_STATUS_ACCESS_DENIED;
160 return NULL;
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.
169 if (strequal(service_in,HOMES_NAME)) {
170 if (session->homes_snum == -1) {
171 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 *status = NT_STATUS_BAD_NETWORK_NAME;
176 return NULL;
178 DEBUG(5, ("making a connection to [homes] service "
179 "created at session setup time\n"));
180 return make_connection_smb1(req, now,
181 session->homes_snum,
182 dev, status);
183 } else if ((session->homes_snum != -1)
184 && strequal(service_in,
185 lp_const_servicename(session->homes_snum))) {
186 DEBUG(5, ("making a connection to 'homes' service [%s] "
187 "created at session setup time\n", service_in));
188 return make_connection_smb1(req, now,
189 session->homes_snum,
190 dev, status);
193 service = talloc_strdup(talloc_tos(), service_in);
194 if (!service) {
195 *status = NT_STATUS_NO_MEMORY;
196 return NULL;
199 if (!strlower_m(service)) {
200 DEBUG(2, ("strlower_m %s failed\n", service));
201 *status = NT_STATUS_INVALID_PARAMETER;
202 return NULL;
205 snum = find_service(talloc_tos(), service, &service);
206 if (!service) {
207 *status = NT_STATUS_NO_MEMORY;
208 return NULL;
211 if (snum < 0) {
212 if (strequal(service,"IPC$") ||
213 (lp_enable_asu_support() && strequal(service,"ADMIN$"))) {
214 DEBUG(3,("refusing IPC connection to %s\n", service));
215 *status = NT_STATUS_ACCESS_DENIED;
216 return NULL;
219 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 *status = NT_STATUS_BAD_NETWORK_NAME;
225 return NULL;
228 /* Handle non-Dfs clients attempting connections to msdfs proxy */
229 if (lp_host_msdfs() && (*lp_msdfs_proxy(talloc_tos(), lp_sub, snum) != '\0')) {
230 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 *status = NT_STATUS_BAD_NETWORK_NAME;
234 return NULL;
237 DEBUG(5, ("making a connection to 'normal' service %s\n", service));
239 return make_connection_smb1(req, now, snum,
240 dev, status);