Print this page
NEX-19781 SMB service shutdown hang with threads in smb_authsock_recv
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-16604 Windows 10 SMB client exhausts smbauth sockets
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-13644 File access audit logging
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-9497 SMB should bypass ACL traverse checking
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-10231 SMB logon fails in fksmbd
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-5273 SMB 3 Encryption
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
NEX-7267 Codenomicon causes panic in smb_authsock_cancel (lint)
NEX-7267 Codenomicon causes panic in smb_authsock_cancel
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-6888 Defensics test causes panic due to bad free
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-5560 smb2 should use 64-bit server-global uids
Reviewed by: Gordon Ross <gwr@nexenta.com>
NEX-2522 svcadm disable network/smb/server may hang
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-3610 CLONE NEX-3591 SMB3 signing
Reviewed by: Gordon Ross <gwr@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
NEX-3611 CLONE NEX-3550 Replace smb2_enable with max_protocol
Reviewed by: Yuri Pankov <Yuri.Pankov@nexenta.com>
NEX-3080 SMB1 signing problem with Kerberos auth.
Reviewed by: Bayard Bell <bayard.bell@nexenta.com>
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-2485 SMB authentication flood handled poorly
SUP-866 smbd lwps stuck in libsocket recv() for no apparent reason
SMB-152 mem leak in smb_authenticate_ext/smb_authsock_sendrecv
SMB-55 SMB2 signing
OS-6 mpathadm leads to panic in vhci_mpapi_sync_lu_oid_list
SMB-85 Codenomicon: SMB2 TC: 16193 - Panic in smb_authenticate_ext
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
SMB-56 extended security NTLMSSP, inbound
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb_authenticate.c
+++ new/usr/src/uts/common/fs/smbsrv/smb_authenticate.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 - * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
23 + * Copyright 2019 Nexenta Systems, Inc. All rights reserved.
24 24 */
25 25
26 26 /*
27 27 * Authentication support for SMB session setup
28 28 */
29 29
30 30 #include <sys/types.h>
31 31 #include <sys/sid.h>
32 32 #include <sys/priv_names.h>
33 33 #include <sys/socket.h>
34 34 #include <sys/un.h>
35 35 #include <netinet/in.h>
36 36 #include <smbsrv/smb_idmap.h>
37 37 #include <smbsrv/smb_kproto.h>
38 38 #include <smbsrv/smb_token.h>
39 39
40 -static uint32_t smb_authsock_open(smb_user_t *);
40 +static uint32_t smb_authsock_open(smb_request_t *);
41 41 static int smb_authsock_send(ksocket_t, void *, size_t);
42 42 static int smb_authsock_recv(ksocket_t, void *, size_t);
43 -static uint32_t smb_authsock_sendrecv(smb_user_t *, smb_lsa_msg_hdr_t *hdr,
43 +static uint32_t smb_authsock_sendrecv(smb_request_t *, smb_lsa_msg_hdr_t *hdr,
44 44 void *sndbuf, void **recvbuf);
45 45 /* void smb_authsock_close(smb_user_t *); kproto.h */
46 46
47 47 static uint32_t smb_auth_do_clinfo(smb_request_t *);
48 48 static uint32_t smb_auth_do_oldreq(smb_request_t *);
49 49 static uint32_t smb_auth_get_token(smb_request_t *);
50 50 static uint32_t smb_priv_xlate(smb_token_t *);
51 51
52 52 /*
53 53 * Handle old-style session setup (non-extended security)
54 + * Note: Used only by SMB1
54 55 *
55 56 * The user information is passed to smbd for authentication.
56 57 * If smbd can authenticate the user an access token is returned and we
57 58 * generate a cred and new user based on the token.
58 59 */
59 60 int
60 61 smb_authenticate_old(smb_request_t *sr)
61 62 {
62 63 smb_user_t *user = NULL;
63 64 uint32_t status;
64 65
65 66 user = smb_user_new(sr->session);
66 67 if (user == NULL)
67 68 return (NT_STATUS_TOO_MANY_SESSIONS);
68 69
69 70 /* user cleanup in smb_request_free */
70 71 sr->uid_user = user;
71 72 sr->smb_uid = user->u_uid;
73 + sr->smb2_ssnid = 0;
72 74
73 75 /*
74 76 * Open a connection to the local logon service.
75 77 * If we can't, it may be busy, or not running.
76 78 * Don't log here - this may be frequent.
77 79 */
78 - if ((status = smb_authsock_open(user)) != 0)
80 + if ((status = smb_authsock_open(sr)) != 0)
79 81 goto errout;
80 82
81 83 /*
82 84 * Tell the auth. svc who this client is.
83 85 */
84 86 if ((status = smb_auth_do_clinfo(sr)) != 0)
85 87 goto errout;
86 88
87 89 /*
88 90 * Authentication proper
89 91 */
90 92 if ((status = smb_auth_do_oldreq(sr)) != 0)
91 93 goto errout;
92 94
93 95 /*
94 96 * Get the final auth. token.
95 97 */
96 98 if ((status = smb_auth_get_token(sr)) != 0)
97 99 goto errout;
98 100
99 101 return (0);
100 102
101 103 errout:
102 104 smb_user_logoff(user);
103 105 return (status);
104 106 }
105 107
106 108 /*
|
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
107 109 * Build an authentication request message and
108 110 * send it to the local logon service.
109 111 */
110 112 static uint32_t
111 113 smb_auth_do_oldreq(smb_request_t *sr)
112 114 {
113 115 smb_lsa_msg_hdr_t msg_hdr;
114 116 smb_logon_t user_info;
115 117 XDR xdrs;
116 118 smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
117 - smb_user_t *user = sr->uid_user;
118 119 void *sbuf = NULL;
119 120 void *rbuf = NULL;
120 121 uint32_t slen = 0;
121 122 uint32_t rlen = 0;
122 123 uint32_t status;
123 124 bool_t ok;
124 125
125 126 bzero(&user_info, sizeof (smb_logon_t));
126 127
127 128 user_info.lg_level = NETR_NETWORK_LOGON;
128 129 user_info.lg_username = sinfo->ssi_user;
129 130 user_info.lg_domain = sinfo->ssi_domain;
130 131 user_info.lg_workstation = sr->session->workstation;
131 132 user_info.lg_clnt_ipaddr = sr->session->ipaddr;
132 133 user_info.lg_local_ipaddr = sr->session->local_ipaddr;
133 134 user_info.lg_local_port = sr->session->s_local_port;
134 135 user_info.lg_challenge_key.val = sr->session->challenge_key;
135 136 user_info.lg_challenge_key.len = sr->session->challenge_len;
136 137 user_info.lg_nt_password.val = sinfo->ssi_ntpwd;
137 138 user_info.lg_nt_password.len = sinfo->ssi_ntpwlen;
138 139 user_info.lg_lm_password.val = sinfo->ssi_lmpwd;
139 140 user_info.lg_lm_password.len = sinfo->ssi_lmpwlen;
140 141 user_info.lg_native_os = sr->session->native_os;
141 142 user_info.lg_native_lm = sr->session->native_lm;
142 143 /* lg_flags? */
143 144
144 145 slen = xdr_sizeof(smb_logon_xdr, &user_info);
145 146 sbuf = kmem_alloc(slen, KM_SLEEP);
|
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
146 147 xdrmem_create(&xdrs, sbuf, slen, XDR_ENCODE);
147 148 ok = smb_logon_xdr(&xdrs, &user_info);
148 149 xdr_destroy(&xdrs);
149 150 if (!ok) {
150 151 status = RPC_NT_BAD_STUB_DATA;
151 152 goto out;
152 153 }
153 154
154 155 msg_hdr.lmh_msgtype = LSA_MTYPE_OLDREQ;
155 156 msg_hdr.lmh_msglen = slen;
156 - status = smb_authsock_sendrecv(user, &msg_hdr, sbuf, &rbuf);
157 + status = smb_authsock_sendrecv(sr, &msg_hdr, sbuf, &rbuf);
157 158 if (status != 0)
158 159 goto out;
159 160 rlen = msg_hdr.lmh_msglen;
160 161 kmem_free(sbuf, slen);
161 162 sbuf = NULL;
162 163
163 164 /*
164 165 * Decode the response message.
165 166 */
166 167 switch (msg_hdr.lmh_msgtype) {
167 168
168 169 case LSA_MTYPE_OK:
169 170 status = 0;
170 171 break;
171 172
172 173 case LSA_MTYPE_ERROR:
173 174 if (rlen == sizeof (smb_lsa_eresp_t)) {
174 175 smb_lsa_eresp_t *ler = rbuf;
175 176 status = ler->ler_ntstatus;
176 177 break;
177 178 }
178 179 /* FALLTHROUGH */
179 180
180 181 default: /* Bogus message type */
181 182 status = NT_STATUS_INTERNAL_ERROR;
182 183 break;
183 184 }
184 185
185 186 out:
186 187 if (rbuf != NULL)
187 188 kmem_free(rbuf, rlen);
188 189 if (sbuf != NULL)
189 190 kmem_free(sbuf, slen);
190 191
191 192 return (status);
192 193 }
193 194
194 195 /*
195 196 * Handle new-style (extended security) session setup.
196 197 * Returns zero: success, non-zero: error (value not used)
197 198 *
198 199 * Note that this style uses a sequence of session setup requests,
199 200 * where the first has SMB UID=0, and subsequent requests in the
200 201 * same authentication sequence have the SMB UID returned for that
201 202 * first request. We allocate a USER object when the first request
202 203 * in the sequence arrives (SMB_USER_STATE_LOGGING_ON) and use that
203 204 * to maintain state between requests in this sequence. The state
204 205 * for one sequence includes an AF_UNIX "authsock" connection to the
205 206 * user-space smbd. The neat part of this is: in smbd, the handler
206 207 * for the server-side of one authsock gets only request specific to
207 208 * one authentication sequence, simplifying it's work immensely.
208 209 * When the authentication sequence is finished, with either success
209 210 * or failure, the local side of the authsock is closed.
210 211 *
211 212 * As with the old-style authentication, if we succeed, then the
212 213 * last message from smbd will be an smb_token_t encoding the
213 214 * information about the new user.
214 215 *
215 216 * Outline:
216 217 * (a) On the first request (UID==0) create a USER object,
217 218 * and on subsequent requests, find USER by SMB UID.
218 219 * (b) Send message / recv. response as above,
219 220 * (c) If response says "we're done", close authsock
220 221 * (both success and failure must close authsock)
221 222 */
222 223 int
223 224 smb_authenticate_ext(smb_request_t *sr)
224 225 {
|
↓ open down ↓ |
58 lines elided |
↑ open up ↑ |
225 226 smb_lsa_msg_hdr_t msg_hdr;
226 227 smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
227 228 smb_user_t *user = NULL;
228 229 void *rbuf = NULL;
229 230 uint32_t rlen = 0;
230 231 uint32_t status;
231 232
232 233 ASSERT(sr->uid_user == NULL);
233 234
234 235 /*
235 - * On the first request (UID==0) create a USER object.
236 - * On subsequent requests (UID!=0) find the USER object.
236 + * Paranoid: While finding/creating the user object, make sure
237 + * SMB2 ignores smb_uid, and SMB1 ignores smb2_ssnid. The
238 + * logic below assumes the "other" one is always zero; both
239 + * the "first request" tests and smb_session_lookup_uid_st.
240 + */
241 + if (sr->session->dialect >= SMB_VERS_2_BASE) {
242 + /* SMB2+ ignores smb_uid */
243 + ASSERT(sr->smb_uid == 0);
244 + sr->smb_uid = 0;
245 + } else {
246 + /* SMB1 ignores smb2_ssnid */
247 + ASSERT(sr->smb2_ssnid == 0);
248 + sr->smb2_ssnid = 0;
249 + }
250 +
251 + /*
252 + * On the first request (UID/ssnid==0) create a USER object.
253 + * On subsequent requests (UID/ssnid!=0) find the USER object.
237 254 * Either way, sr->uid_user is set, so our ref. on the
238 255 * user object is dropped during normal cleanup work
239 256 * for the smb_request (sr). Ditto u_authsock.
240 257 */
241 - if (sr->smb_uid == 0) {
258 + if (sr->smb2_ssnid == 0 && sr->smb_uid == 0) {
242 259 user = smb_user_new(sr->session);
243 260 if (user == NULL)
244 261 return (NT_STATUS_TOO_MANY_SESSIONS);
245 262
246 263 /* user cleanup in smb_request_free */
247 264 sr->uid_user = user;
248 - sr->smb_uid = user->u_uid;
265 + if (sr->session->dialect >= SMB_VERS_2_BASE) {
266 + /* Intentionally leave smb_uid=0 for SMB2 */
267 + sr->smb2_ssnid = user->u_ssnid;
268 + } else {
269 + /* Intentionally leave smb2_ssnid=0 for SMB1 */
270 + sr->smb_uid = user->u_uid;
271 + }
249 272
250 273 /*
251 274 * Open a connection to the local logon service.
252 275 * If we can't, it may be busy, or not running.
253 276 * Don't log here - this may be frequent.
254 277 */
255 - if ((status = smb_authsock_open(user)) != 0)
278 + if ((status = smb_authsock_open(sr)) != 0)
256 279 goto errout;
257 280
258 281 /*
259 282 * Tell the auth. svc who this client is.
260 283 */
261 284 if ((status = smb_auth_do_clinfo(sr)) != 0)
262 285 goto errout;
263 286
264 287 msg_hdr.lmh_msgtype = LSA_MTYPE_ESFIRST;
265 288 } else {
266 289 user = smb_session_lookup_uid_st(sr->session,
267 - sr->smb_uid, SMB_USER_STATE_LOGGING_ON);
290 + sr->smb2_ssnid, sr->smb_uid, SMB_USER_STATE_LOGGING_ON);
268 291 if (user == NULL)
269 292 return (NT_STATUS_USER_SESSION_DELETED);
270 293
271 294 /* user cleanup in smb_request_free */
272 295 sr->uid_user = user;
273 296
274 297 msg_hdr.lmh_msgtype = LSA_MTYPE_ESNEXT;
275 298 }
276 299
277 300 /*
278 301 * Wrap the "security blob" with our header
279 302 * (LSA_MTYPE_ESFIRST or LSA_MTYPE_ESNEXT)
280 303 * and send it up the authsock with either
281 304 */
282 305 msg_hdr.lmh_msglen = sinfo->ssi_iseclen;
283 - status = smb_authsock_sendrecv(user, &msg_hdr,
306 + status = smb_authsock_sendrecv(sr, &msg_hdr,
284 307 sinfo->ssi_isecblob, &rbuf);
285 308 if (status != 0)
286 309 goto errout;
287 310 rlen = msg_hdr.lmh_msglen;
288 311
289 312 /*
290 313 * Decode the response message.
291 314 * Note: allocated rbuf
292 315 */
293 316 switch (msg_hdr.lmh_msgtype) {
294 317
295 318 case LSA_MTYPE_ES_CONT:
296 319 sinfo->ssi_oseclen = (uint16_t)rlen;
297 320 sinfo->ssi_osecblob = smb_srm_alloc(sr, sinfo->ssi_oseclen);
298 321 bcopy(rbuf, sinfo->ssi_osecblob, sinfo->ssi_oseclen);
299 322 /*
300 323 * This is not really an error, but tells the client
301 324 * it should send another session setup request.
302 325 */
303 326 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
304 327 break;
305 328
306 329 case LSA_MTYPE_ES_DONE:
307 330 sinfo->ssi_oseclen = (uint16_t)rlen;
308 331 sinfo->ssi_osecblob = smb_srm_alloc(sr, sinfo->ssi_oseclen);
309 332 bcopy(rbuf, sinfo->ssi_osecblob, sinfo->ssi_oseclen);
310 333 sinfo->ssi_ntpwlen = 0;
311 334 /*
312 335 * Get the final auth. token.
313 336 */
314 337 status = smb_auth_get_token(sr);
315 338 break;
316 339
317 340 case LSA_MTYPE_ERROR:
318 341 /*
319 342 * Authentication failed. Return the error
320 343 * provided in the reply message.
321 344 */
322 345 if (rlen == sizeof (smb_lsa_eresp_t)) {
323 346 smb_lsa_eresp_t *ler = rbuf;
324 347 status = ler->ler_ntstatus;
325 348 goto errout;
326 349 }
327 350 /* FALLTHROUGH */
328 351
329 352 default: /* Bogus message type */
330 353 status = NT_STATUS_INTERNAL_ERROR;
331 354 goto errout;
332 355 }
333 356
334 357 if (status != 0 && status != NT_STATUS_MORE_PROCESSING_REQUIRED) {
335 358 errout:
336 359 smb_user_logoff(user);
337 360 }
338 361
339 362 if (rbuf != NULL)
340 363 kmem_free(rbuf, rlen);
341 364
342 365 return (status);
|
↓ open down ↓ |
49 lines elided |
↑ open up ↑ |
343 366 }
344 367
345 368 /*
346 369 * Send the "client info" up to the auth service.
347 370 */
348 371 static uint32_t
349 372 smb_auth_do_clinfo(smb_request_t *sr)
350 373 {
351 374 smb_lsa_msg_hdr_t msg_hdr;
352 375 smb_lsa_clinfo_t clinfo;
353 - smb_user_t *user = sr->uid_user;
354 376 void *rbuf = NULL;
355 377 uint32_t status;
356 378
357 379 /*
358 380 * Send a message with info. about the client
359 381 * (IP address, etc) and wait for an ACK.
360 382 */
361 383 msg_hdr.lmh_msgtype = LSA_MTYPE_CLINFO;
362 384 msg_hdr.lmh_msglen = sizeof (clinfo);
363 385 clinfo.lci_clnt_ipaddr = sr->session->ipaddr;
364 386 (void) memcpy(clinfo.lci_challenge_key,
365 387 sr->session->challenge_key,
366 388 sizeof (clinfo.lci_challenge_key));
367 - status = smb_authsock_sendrecv(user, &msg_hdr, &clinfo, &rbuf);
389 + status = smb_authsock_sendrecv(sr, &msg_hdr, &clinfo, &rbuf);
368 390 /* We don't use this response. */
369 391 if (rbuf != NULL) {
370 392 kmem_free(rbuf, msg_hdr.lmh_msglen);
371 393 rbuf = NULL;
372 394 }
373 395
374 396 return (status);
375 397 }
376 398
377 399 /*
378 400 * After a successful authentication, ask the authsvc to
379 401 * send us the authentication token.
380 402 */
381 403 static uint32_t
382 404 smb_auth_get_token(smb_request_t *sr)
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
383 405 {
384 406 smb_lsa_msg_hdr_t msg_hdr;
385 407 XDR xdrs;
386 408 smb_user_t *user = sr->uid_user;
387 409 smb_token_t *token = NULL;
388 410 cred_t *cr = NULL;
389 411 void *rbuf = NULL;
390 412 uint32_t rlen = 0;
391 413 uint32_t privileges;
392 414 uint32_t status;
393 - int rc;
394 415 bool_t ok;
395 416
396 417 msg_hdr.lmh_msgtype = LSA_MTYPE_GETTOK;
397 418 msg_hdr.lmh_msglen = 0;
398 419
399 - status = smb_authsock_sendrecv(user, &msg_hdr, NULL, &rbuf);
420 + status = smb_authsock_sendrecv(sr, &msg_hdr, NULL, &rbuf);
400 421 if (status != 0)
401 422 goto errout;
402 423
403 424 rlen = msg_hdr.lmh_msglen;
404 425 switch (msg_hdr.lmh_msgtype) {
405 426
406 427 case LSA_MTYPE_TOKEN:
407 428 status = 0;
408 429 break;
409 430
410 431 case LSA_MTYPE_ERROR:
411 432 if (rlen == sizeof (smb_lsa_eresp_t)) {
412 433 smb_lsa_eresp_t *ler = rbuf;
413 434 status = ler->ler_ntstatus;
414 435 goto errout;
415 436 }
416 437 /* FALLTHROUGH */
417 438
418 439 default:
419 440 status = NT_STATUS_INTERNAL_ERROR;
420 441 goto errout;
421 442 }
422 443
423 444 /*
424 445 * Authenticated. Decode the LSA_MTYPE_TOKEN.
425 446 */
426 447 xdrmem_create(&xdrs, rbuf, rlen, XDR_DECODE);
427 448 token = kmem_zalloc(sizeof (smb_token_t), KM_SLEEP);
428 449 ok = smb_token_xdr(&xdrs, token);
429 450 xdr_destroy(&xdrs);
|
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
430 451 if (!ok) {
431 452 status = RPC_NT_BAD_STUB_DATA;
432 453 goto errout;
433 454 }
434 455 kmem_free(rbuf, rlen);
435 456 rbuf = NULL;
436 457
437 458 /*
438 459 * Setup the logon object.
439 460 */
440 - cr = smb_cred_create(token);
461 + cr = smb_cred_create(token, sr->session);
441 462 if (cr == NULL)
442 463 goto errout;
443 464 privileges = smb_priv_xlate(token);
444 465 (void) smb_user_logon(user, cr,
445 466 token->tkn_domain_name, token->tkn_account_name,
446 467 token->tkn_flags, privileges, token->tkn_audit_sid);
447 468 crfree(cr);
448 469
449 470 /*
471 + * Some basic processing for encryption needs to be done,
472 + * even for anonymous/guest sessions. In particular,
473 + * we need to set Session.EncryptData.
474 + *
475 + * Windows handling of anon/guest and encryption is strange.
476 + * It allows these accounts to get through session setup,
477 + * even when they provide no key material.
478 + * Additionally, Windows somehow manages to have key material
479 + * for anonymous accounts under unknown circumstances.
480 + * As such, We set EncryptData on anon/guest to behave like Windows,
481 + * at least through Session Setup.
482 + */
483 + if (sr->session->dialect >= SMB_VERS_3_0)
484 + smb3_encrypt_begin(sr, token);
485 +
486 + /*
450 487 * Save the session key, and (maybe) enable signing,
451 488 * but only for real logon (not ANON or GUEST).
452 489 */
453 490 if ((token->tkn_flags & (SMB_ATF_GUEST | SMB_ATF_ANON)) == 0) {
454 491 if (sr->session->dialect >= SMB_VERS_2_BASE) {
455 - rc = smb2_sign_begin(sr, token);
492 + smb2_sign_begin(sr, token);
456 493 } else {
457 - rc = smb_sign_begin(sr, token);
494 + smb_sign_begin(sr, token);
458 495 }
459 - if (rc != 0) {
460 - status = NT_STATUS_INTERNAL_ERROR;
461 - goto errout;
462 - }
463 496 }
464 497
465 498 smb_token_free(token);
466 499
467 500 sr->user_cr = user->u_cred;
468 501 return (0);
469 502
470 503 errout:
471 504 if (rbuf != NULL)
472 505 kmem_free(rbuf, rlen);
473 506 if (token != NULL)
474 507 smb_token_free(token);
475 508 return (status);
476 509 }
477 510
478 511 /*
479 512 * Tokens are allocated in the kernel via XDR.
480 513 * Call xdr_free before freeing the token structure.
481 514 */
482 515 void
483 516 smb_token_free(smb_token_t *token)
484 517 {
485 518 if (token != NULL) {
486 519 xdr_free(smb_token_xdr, (char *)token);
487 520 kmem_free(token, sizeof (smb_token_t));
488 521 }
|
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
489 522 }
490 523
491 524 /*
492 525 * Convert access token privileges to local definitions.
493 526 */
494 527 static uint32_t
495 528 smb_priv_xlate(smb_token_t *token)
496 529 {
497 530 uint32_t privileges = 0;
498 531
532 + if (smb_token_query_privilege(token, SE_SECURITY_LUID))
533 + privileges |= SMB_USER_PRIV_SECURITY;
534 +
535 + if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID))
536 + privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP;
537 +
499 538 if (smb_token_query_privilege(token, SE_BACKUP_LUID))
500 539 privileges |= SMB_USER_PRIV_BACKUP;
501 540
502 541 if (smb_token_query_privilege(token, SE_RESTORE_LUID))
503 542 privileges |= SMB_USER_PRIV_RESTORE;
504 543
505 - if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID))
506 - privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP;
544 + if (smb_token_query_privilege(token, SE_CHANGE_NOTIFY_LUID))
545 + privileges |= SMB_USER_PRIV_CHANGE_NOTIFY;
507 546
508 - if (smb_token_query_privilege(token, SE_SECURITY_LUID))
509 - privileges |= SMB_USER_PRIV_SECURITY;
510 -
511 547 return (privileges);
512 548 }
513 549
514 550 /*
551 + * Unblock a request that might be blocked reading some
552 + * authentication socket. This can happen when either the
553 + * client cancels a session setup or closes the connection.
554 + */
555 +static void
556 +smb_authsock_cancel(smb_request_t *sr)
557 +{
558 + smb_user_t *user = sr->cancel_arg2;
559 + ksocket_t authsock = NULL;
560 +
561 + if (user == NULL)
562 + return;
563 + ASSERT(user == sr->uid_user);
564 +
565 + /*
566 + * Check user state, and get a hold on the auth socket.
567 + */
568 + mutex_enter(&user->u_mutex);
569 + if (user->u_state == SMB_USER_STATE_LOGGING_ON) {
570 + if ((authsock = user->u_authsock) != NULL)
571 + ksocket_hold(authsock);
572 + }
573 + mutex_exit(&user->u_mutex);
574 +
575 + if (authsock != NULL) {
576 + (void) ksocket_shutdown(authsock, SHUT_RDWR, sr->user_cr);
577 + ksocket_rele(authsock);
578 + }
579 +}
580 +
581 +/*
515 582 * Send/recv a request/reply sequence on the auth socket.
516 583 * Returns zero or an NT status.
517 584 *
518 585 * Errors here mean we can't communicate with the smbd_authsvc.
519 586 * With limited authsock instances, this should be rare.
520 587 */
521 588 static uint32_t
522 -smb_authsock_sendrecv(smb_user_t *user, smb_lsa_msg_hdr_t *hdr,
523 - void *sndbuf, void **recvbuf)
589 +smb_authsock_sendrecv(smb_request_t *sr, smb_lsa_msg_hdr_t *hdr,
590 + void *sndbuf, void **recvbuf)
524 591 {
592 + smb_user_t *user = sr->uid_user;
525 593 ksocket_t so;
526 594 uint32_t status;
527 595 int rc;
528 596
529 597 /*
530 598 * Get a hold on the auth socket.
531 599 */
532 600 mutex_enter(&user->u_mutex);
533 601 so = user->u_authsock;
534 602 if (so == NULL) {
535 603 mutex_exit(&user->u_mutex);
536 604 return (NT_STATUS_INTERNAL_ERROR);
537 605 }
538 606 ksocket_hold(so);
539 607 mutex_exit(&user->u_mutex);
540 608
609 + mutex_enter(&sr->sr_mutex);
610 + if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
611 + mutex_exit(&sr->sr_mutex);
612 + status = NT_STATUS_CANCELLED;
613 + goto out;
614 + }
615 + sr->sr_state = SMB_REQ_STATE_WAITING_AUTH;
616 + sr->cancel_method = smb_authsock_cancel;
617 + sr->cancel_arg2 = user;
618 + mutex_exit(&sr->sr_mutex);
619 +
541 620 rc = smb_authsock_send(so, hdr, sizeof (*hdr));
542 621 if (rc == 0 && hdr->lmh_msglen != 0) {
543 622 rc = smb_authsock_send(so, sndbuf, hdr->lmh_msglen);
544 623 }
545 - if (rc)
546 - goto out;
547 -
548 - rc = smb_authsock_recv(so, hdr, sizeof (*hdr));
624 + if (rc == 0)
625 + rc = smb_authsock_recv(so, hdr, sizeof (*hdr));
549 626 if (rc == 0 && hdr->lmh_msglen != 0) {
550 627 *recvbuf = kmem_alloc(hdr->lmh_msglen, KM_SLEEP);
551 628 rc = smb_authsock_recv(so, *recvbuf, hdr->lmh_msglen);
552 - if (rc) {
553 - kmem_free(*recvbuf, hdr->lmh_msglen);
554 - *recvbuf = NULL;
555 - }
556 629 }
557 630
558 -out:
559 - ksocket_rele(so);
560 631 switch (rc) {
561 632 case 0:
562 633 status = 0;
563 634 break;
564 635 case EIO:
565 636 status = RPC_NT_COMM_FAILURE;
566 637 break;
567 638 case ENOTCONN:
568 639 status = RPC_NT_PIPE_CLOSED;
569 640 break;
570 641 default:
571 642 status = RPC_NT_CALL_FAILED;
572 643 break;
573 644 }
574 645
646 + mutex_enter(&sr->sr_mutex);
647 + sr->cancel_method = NULL;
648 + sr->cancel_arg2 = NULL;
649 + switch (sr->sr_state) {
650 + case SMB_REQ_STATE_WAITING_AUTH:
651 + sr->sr_state = SMB_REQ_STATE_ACTIVE;
652 + break;
653 + case SMB_REQ_STATE_CANCEL_PENDING:
654 + sr->sr_state = SMB_REQ_STATE_CANCELLED;
655 + status = NT_STATUS_CANCELLED;
656 + break;
657 + default:
658 + status = NT_STATUS_INTERNAL_ERROR;
659 + break;
660 + }
661 + mutex_exit(&sr->sr_mutex);
662 +
663 +out:
664 + ksocket_rele(so);
665 +
666 + if (status != 0 && *recvbuf != NULL) {
667 + kmem_free(*recvbuf, hdr->lmh_msglen);
668 + *recvbuf = NULL;
669 + }
575 670 return (status);
576 671 }
577 672
578 673 /*
579 674 * Hope this is interpreted per-zone...
580 675 */
581 676 static struct sockaddr_un smbauth_sockname = {
582 677 AF_UNIX, SMB_AUTHSVC_SOCKNAME };
583 678
584 679 /*
585 680 * Limit how long smb_authsock_sendrecv() will wait for a
|
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
586 681 * response from the local authentication service.
587 682 */
588 683 struct timeval smb_auth_recv_tmo = { 45, 0 };
589 684
590 685 /*
591 686 * Also limit the time smb_authsock_sendrecv() will wait
592 687 * trying to send a request to the authentication service.
593 688 */
594 689 struct timeval smb_auth_send_tmo = { 15, 0 };
595 690
691 +/*
692 + * Maximum time a user object may stay in state LOGGING_ON
693 + */
694 +int smb_auth_total_tmo = 45; /* seconds */
695 +
596 696 static uint32_t
597 -smb_authsock_open(smb_user_t *user)
697 +smb_authsock_open(smb_request_t *sr)
598 698 {
599 - smb_server_t *sv = user->u_server;
699 + smb_user_t *user = sr->uid_user;
700 + smb_server_t *sv = sr->sr_server;
600 701 ksocket_t so = NULL;
601 - uint32_t status;
702 + uint32_t status = 0;
602 703 int rc;
603 704
604 705 /*
605 - * If the auth. service is busy, wait our turn.
606 - * This may be frequent, so don't log.
706 + * If the auth. service is busy, wait our turn. This threshold
707 + * limits the number of auth sockets we might have trying to
708 + * communicate with the auth. service up in smbd. Until we've
709 + * set u_authsock, we need to "exit this threshold" in any
710 + * error code paths after this "enter".
711 + *
712 + * Failure to "enter" may be frequent, so don't log.
607 713 */
608 714 if ((rc = smb_threshold_enter(&sv->sv_ssetup_ct)) != 0)
609 715 return (NT_STATUS_NO_LOGON_SERVERS);
610 716
611 717 rc = ksocket_socket(&so, AF_UNIX, SOCK_STREAM, 0,
612 718 KSOCKET_SLEEP, CRED());
613 719 if (rc != 0) {
614 720 cmn_err(CE_NOTE, "smb_authsock_open: socket, rc=%d", rc);
721 + smb_threshold_exit(&sv->sv_ssetup_ct);
615 722 status = NT_STATUS_INSUFF_SERVER_RESOURCES;
616 723 goto errout;
617 724 }
618 725
619 726 /*
727 + * This (new) user object now gets an authsocket.
728 + * Note: u_authsock cleanup in smb_user_logoff.
729 + * After we've set u_authsock, smb_threshold_exit
730 + * is done in smb_authsock_close(). If we somehow
731 + * already have an authsock, close the new one and
732 + * error out.
733 + */
734 + mutex_enter(&user->u_mutex);
735 + if (user->u_authsock != NULL) {
736 + mutex_exit(&user->u_mutex);
737 + smb_authsock_close(user, so);
738 + status = NT_STATUS_INTERNAL_ERROR;
739 + goto errout;
740 + }
741 + user->u_authsock = so;
742 + if (smb_auth_total_tmo != 0) {
743 + user->u_auth_tmo = timeout(smb_user_auth_tmo, user,
744 + SEC_TO_TICK(smb_auth_total_tmo));
745 + }
746 + mutex_exit(&user->u_mutex);
747 +
748 + /*
620 749 * Set the send/recv timeouts.
621 750 */
622 751 (void) ksocket_setsockopt(so, SOL_SOCKET, SO_SNDTIMEO,
623 752 &smb_auth_send_tmo, sizeof (smb_auth_send_tmo), CRED());
624 753 (void) ksocket_setsockopt(so, SOL_SOCKET, SO_RCVTIMEO,
625 754 &smb_auth_recv_tmo, sizeof (smb_auth_recv_tmo), CRED());
626 755
627 756 /*
628 757 * Connect to the smbd auth. service.
629 758 *
630 759 * Would like to set the connect timeout too, but there's
631 760 * apparently no easy way to do that for AF_UNIX.
632 761 */
762 + mutex_enter(&sr->sr_mutex);
763 + if (sr->sr_state != SMB_REQ_STATE_ACTIVE) {
764 + mutex_exit(&sr->sr_mutex);
765 + status = NT_STATUS_CANCELLED;
766 + goto errout;
767 + }
768 + sr->sr_state = SMB_REQ_STATE_WAITING_AUTH;
769 + sr->cancel_method = smb_authsock_cancel;
770 + sr->cancel_arg2 = user;
771 + mutex_exit(&sr->sr_mutex);
772 +
633 773 rc = ksocket_connect(so, (struct sockaddr *)&smbauth_sockname,
634 774 sizeof (smbauth_sockname), CRED());
635 775 if (rc != 0) {
636 776 DTRACE_PROBE1(error, int, rc);
637 777 status = NT_STATUS_NETLOGON_NOT_STARTED;
638 - goto errout;
639 778 }
640 779
641 - /* Note: u_authsock cleanup in smb_authsock_close() */
642 - mutex_enter(&user->u_mutex);
643 - if (user->u_authsock != NULL) {
644 - mutex_exit(&user->u_mutex);
780 + mutex_enter(&sr->sr_mutex);
781 + sr->cancel_method = NULL;
782 + sr->cancel_arg2 = NULL;
783 + switch (sr->sr_state) {
784 + case SMB_REQ_STATE_WAITING_AUTH:
785 + sr->sr_state = SMB_REQ_STATE_ACTIVE;
786 + break;
787 + case SMB_REQ_STATE_CANCEL_PENDING:
788 + sr->sr_state = SMB_REQ_STATE_CANCELLED;
789 + status = NT_STATUS_CANCELLED;
790 + break;
791 + default:
645 792 status = NT_STATUS_INTERNAL_ERROR;
646 - goto errout;
793 + break;
647 794 }
648 - user->u_authsock = so;
649 - mutex_exit(&user->u_mutex);
650 - return (0);
795 + mutex_exit(&sr->sr_mutex);
651 796
652 797 errout:
653 - if (so != NULL)
654 - (void) ksocket_close(so, CRED());
655 - smb_threshold_exit(&sv->sv_ssetup_ct);
656 -
657 798 return (status);
658 799 }
659 800
660 801 static int
661 802 smb_authsock_send(ksocket_t so, void *buf, size_t len)
662 803 {
663 804 int rc;
664 805 size_t iocnt = 0;
665 806
666 807 rc = ksocket_send(so, buf, len, 0, &iocnt, CRED());
667 808 if (rc == 0 && iocnt != len) {
668 809 DTRACE_PROBE1(short, size_t, iocnt);
669 810 rc = EIO;
670 811 }
671 812 if (rc != 0) {
672 813 DTRACE_PROBE1(error, int, rc);
673 814 }
674 815
675 816 return (rc);
676 817 }
677 818
678 819 static int
679 820 smb_authsock_recv(ksocket_t so, void *buf, size_t len)
680 821 {
681 822 int rc;
682 823 size_t iocnt = 0;
683 824
684 825 rc = ksocket_recv(so, buf, len, MSG_WAITALL, &iocnt, CRED());
685 826 if (rc == 0) {
686 827 if (iocnt == 0) {
687 828 DTRACE_PROBE1(discon, struct sonode *, so);
688 829 rc = ENOTCONN;
689 830 } else if (iocnt != len) {
690 831 /* Should not happen with MSG_WAITALL */
691 832 DTRACE_PROBE1(short, size_t, iocnt);
|
↓ open down ↓ |
25 lines elided |
↑ open up ↑ |
692 833 rc = EIO;
693 834 }
694 835 }
695 836 if (rc != 0) {
696 837 DTRACE_PROBE1(error, int, rc);
697 838 }
698 839
699 840 return (rc);
700 841 }
701 842
843 +/*
844 + * Caller has cleared user->u_authsock, passing the last ref
845 + * as the 2nd arg here. This can block, so it's called
846 + * after exiting u_mutex.
847 + */
702 848 void
703 -smb_authsock_close(smb_user_t *user)
849 +smb_authsock_close(smb_user_t *user, ksocket_t so)
704 850 {
705 851
706 - ASSERT(MUTEX_HELD(&user->u_mutex));
707 - if (user->u_authsock == NULL)
708 - return;
709 - (void) ksocket_close(user->u_authsock, CRED());
710 - user->u_authsock = NULL;
852 + (void) ksocket_shutdown(so, SHUT_RDWR, CRED());
853 + (void) ksocket_close(so, CRED());
711 854 smb_threshold_exit(&user->u_server->sv_ssetup_ct);
712 855 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX