1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 #include <sys/types.h>
26 #include <sys/sid.h>
27 #include <sys/priv_names.h>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
30 #include <smbsrv/smb_idmap.h>
31 #include <smbsrv/smb_kproto.h>
32 #include <smbsrv/smb_token.h>
33
34 static int smb_authenticate(smb_request_t *, smb_arg_sessionsetup_t *,
35 smb_session_key_t **);
36 static int smb_authenticate_core(smb_request_t *, smb_arg_sessionsetup_t *,
37 smb_session_key_t **);
38 static cred_t *smb_cred_create(smb_token_t *);
39 static void smb_cred_set_sid(smb_id_t *id, ksid_t *ksid);
40 static ksidlist_t *smb_cred_set_sidlist(smb_ids_t *token_grps);
41 static uint32_t smb_priv_xlate(smb_token_t *);
42
43 /*
44 * In NTLM 0.12, the padding between the Native OS and Native LM is a bit
45 * strange. On NT4.0, there is a 2 byte pad between the OS (Windows NT 1381)
46 * and LM (Windows NT 4.0). On Windows 2000, there is no padding between
47 * the OS (Windows 2000 2195) and LM (Windows 2000 5.0).
48 * If the padding is removed from the decode string the NT4.0 LM comes out
49 * as an empty string. So if the client's native OS is Win NT we consider
50 * the padding otherwise we don't.
51 *
52 * For Pre-NTLM 0.12, despite the CIFS/1.0 spec, the user and domain are
53 * not always present in the message. We try to get the account name and
54 * the primary domain but we don't care about the the native OS or native
55 * LM fields.
56 *
57 * If the Native LM cannot be determined, default to Windows NT.
58 */
59 smb_sdrc_t
smb_pre_session_setup_andx(smb_request_t * sr)60 smb_pre_session_setup_andx(smb_request_t *sr)
61 {
62 smb_arg_sessionsetup_t *sinfo;
63 char *native_os;
64 char *native_lm;
65 uint16_t maxbufsize;
66 uint16_t vcnumber;
67 int rc = 0;
68
69 sinfo = smb_srm_zalloc(sr, sizeof (smb_arg_sessionsetup_t));
70 sr->sr_ssetup = sinfo;
71
72 if (sr->session->dialect >= NT_LM_0_12) {
73 rc = smbsr_decode_vwv(sr, "b.wwwwlww4.l", &sr->andx_com,
74 &sr->andx_off, &maxbufsize,
75 &sinfo->ssi_maxmpxcount, &vcnumber,
76 &sinfo->ssi_sesskey, &sinfo->ssi_cipwlen,
77 &sinfo->ssi_cspwlen, &sinfo->ssi_capabilities);
78 if (rc != 0)
79 goto pre_session_setup_andx_done;
80
81 sinfo->ssi_cipwd = smb_srm_zalloc(sr, sinfo->ssi_cipwlen + 1);
82 sinfo->ssi_cspwd = smb_srm_zalloc(sr, sinfo->ssi_cspwlen + 1);
83
84 rc = smbsr_decode_data(sr, "%#c#cuuu",
85 sr,
86 sinfo->ssi_cipwlen, sinfo->ssi_cipwd,
87 sinfo->ssi_cspwlen, sinfo->ssi_cspwd,
88 &sinfo->ssi_user,
89 &sinfo->ssi_domain,
90 &native_os);
91 if (rc != 0)
92 goto pre_session_setup_andx_done;
93
94 sinfo->ssi_cipwd[sinfo->ssi_cipwlen] = 0;
95 sinfo->ssi_cspwd[sinfo->ssi_cspwlen] = 0;
96
97 sr->session->native_os = smbnative_os_value(native_os);
98
99 if (sr->session->native_os == NATIVE_OS_WINNT)
100 rc = smbsr_decode_data(sr, "%,u", sr, &native_lm);
101 else
102 rc = smbsr_decode_data(sr, "%u", sr, &native_lm);
103
104 if (rc != 0 || native_lm == NULL)
105 native_lm = "NT LAN Manager 4.0";
106
107 sr->session->native_lm = smbnative_lm_value(native_lm);
108 } else {
109 rc = smbsr_decode_vwv(sr, "b.wwwwlw4.", &sr->andx_com,
110 &sr->andx_off, &maxbufsize,
111 &sinfo->ssi_maxmpxcount, &vcnumber,
112 &sinfo->ssi_sesskey, &sinfo->ssi_cipwlen);
113 if (rc != 0)
114 goto pre_session_setup_andx_done;
115
116 sinfo->ssi_cipwd = smb_srm_zalloc(sr, sinfo->ssi_cipwlen + 1);
117 rc = smbsr_decode_data(sr, "%#c", sr, sinfo->ssi_cipwlen,
118 sinfo->ssi_cipwd);
119 if (rc != 0)
120 goto pre_session_setup_andx_done;
121
122 sinfo->ssi_cipwd[sinfo->ssi_cipwlen] = 0;
123
124 if (smbsr_decode_data(sr, "%u", sr, &sinfo->ssi_user) != 0)
125 sinfo->ssi_user = "";
126
127 if (smbsr_decode_data(sr, "%u", sr, &sinfo->ssi_domain) != 0)
128 sinfo->ssi_domain = "";
129
130 native_lm = "NT LAN Manager 4.0";
131 sr->session->native_os = NATIVE_OS_WINNT;
132 sr->session->native_lm = smbnative_lm_value(native_lm);
133 }
134
135 sr->session->vcnumber = vcnumber;
136 sr->session->smb_msg_size = maxbufsize;
137
138 pre_session_setup_andx_done:
139 DTRACE_SMB_2(op__SessionSetupX__start, smb_request_t *, sr,
140 smb_arg_sessionsetup_t, sinfo);
141 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
142 }
143
144 void
smb_post_session_setup_andx(smb_request_t * sr)145 smb_post_session_setup_andx(smb_request_t *sr)
146 {
147 smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
148
149 DTRACE_SMB_2(op__SessionSetupX__done, smb_request_t *, sr,
150 smb_arg_sessionsetup_t, sinfo);
151
152 if (sinfo->ssi_cipwd != NULL)
153 bzero(sinfo->ssi_cipwd, sinfo->ssi_cipwlen + 1);
154
155 if (sinfo->ssi_cspwd != NULL)
156 bzero(sinfo->ssi_cspwd, sinfo->ssi_cspwlen + 1);
157 }
158
159 /*
160 * If the vcnumber is zero, discard any other connections associated with
161 * this client.
162 *
163 * If signing has not already been enabled on this session check to see if
164 * it should be enabled. The first authenticated logon provides the MAC
165 * key and sequence numbers for signing all subsequent sessions on the same
166 * connection.
167 *
168 * NT systems use different native OS and native LanMan values dependent on
169 * whether they are acting as a client or a server. NT 4.0 server responds
170 * with the following values:
171 *
172 * NativeOS: Windows NT 4.0
173 * NativeLM: NT LAN Manager 4.0
174 */
175 smb_sdrc_t
smb_com_session_setup_andx(smb_request_t * sr)176 smb_com_session_setup_andx(smb_request_t *sr)
177 {
178 smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
179 smb_session_key_t *session_key = NULL;
180 char ipaddr_buf[INET6_ADDRSTRLEN];
181 int rc;
182
183 if (sr->session->vcnumber == 0)
184 smb_server_reconnection_check(sr->sr_server, sr->session);
185
186 if (smb_authenticate(sr, sinfo, &session_key) != 0)
187 return (SDRC_ERROR);
188
189 if (sr->session->native_lm == NATIVE_LM_WIN2000)
190 sinfo->ssi_capabilities |= CAP_LARGE_FILES |
191 CAP_LARGE_READX | CAP_LARGE_WRITEX;
192
193 if (!smb_oplock_levelII)
194 sr->session->capabilities &= ~CAP_LEVEL_II_OPLOCKS;
195
196 sr->session->capabilities = sinfo->ssi_capabilities;
197
198 if (!(sr->session->signing.flags & SMB_SIGNING_ENABLED) &&
199 (sr->session->secmode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) &&
200 (sr->smb_flg2 & SMB_FLAGS2_SMB_SECURITY_SIGNATURE) &&
201 session_key)
202 smb_sign_init(sr, session_key, (char *)sinfo->ssi_cspwd,
203 sinfo->ssi_cspwlen);
204
205 if (!(sr->smb_flg2 & SMB_FLAGS2_SMB_SECURITY_SIGNATURE) &&
206 (sr->sr_cfg->skc_signing_required)) {
207 (void) smb_inet_ntop(&sr->session->ipaddr, ipaddr_buf,
208 SMB_IPSTRLEN(sr->session->ipaddr.a_family));
209 cmn_err(CE_NOTE,
210 "SmbSessonSetupX: client %s does not support signing",
211 ipaddr_buf);
212 smbsr_error(sr, NT_STATUS_LOGON_FAILURE,
213 ERRDOS, ERROR_LOGON_FAILURE);
214 return (SDRC_ERROR);
215 }
216
217 rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.www%uuu",
218 3,
219 sr->andx_com,
220 -1, /* andx_off */
221 sinfo->ssi_guest ? 1 : 0,
222 VAR_BCC,
223 sr,
224 smbnative_os_str(&sr->sr_cfg->skc_version),
225 smbnative_lm_str(&sr->sr_cfg->skc_version),
226 sr->sr_cfg->skc_nbdomain);
227
228 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
229 }
230
231 static int
smb_authenticate(smb_request_t * sr,smb_arg_sessionsetup_t * sinfo,smb_session_key_t ** session_key)232 smb_authenticate(smb_request_t *sr, smb_arg_sessionsetup_t *sinfo,
233 smb_session_key_t **session_key)
234 {
235 int rc;
236 smb_server_t *sv = sr->sr_server;
237
238 if (smb_threshold_enter(&sv->sv_ssetup_ct) != 0) {
239 smbsr_error(sr, RPC_NT_SERVER_TOO_BUSY, 0, 0);
240 return (-1);
241 }
242
243 rc = smb_authenticate_core(sr, sinfo, session_key);
244 smb_threshold_exit(&sv->sv_ssetup_ct, sv);
245 return (rc);
246 }
247
248 /*
249 * Authenticate a user. If the user has already been authenticated on
250 * this session, we can simply dup the user and return.
251 *
252 * Otherwise, the user information is passed to smbd for authentication.
253 * If smbd can authenticate the user an access token is returned and we
254 * generate a cred and new user based on the token.
255 */
256 static int
smb_authenticate_core(smb_request_t * sr,smb_arg_sessionsetup_t * sinfo,smb_session_key_t ** session_key)257 smb_authenticate_core(smb_request_t *sr, smb_arg_sessionsetup_t *sinfo,
258 smb_session_key_t **session_key)
259 {
260 char *hostname = sr->sr_cfg->skc_hostname;
261 int security = sr->sr_cfg->skc_secmode;
262 smb_token_t *token = NULL;
263 smb_user_t *user = NULL;
264 smb_logon_t user_info;
265 boolean_t need_lookup = B_FALSE;
266 uint32_t privileges;
267 cred_t *cr;
268 char *buf = NULL;
269 char *p;
270
271 bzero(&user_info, sizeof (smb_logon_t));
272 user_info.lg_e_domain = sinfo->ssi_domain;
273
274 if ((*sinfo->ssi_user == '\0') &&
275 (sinfo->ssi_cspwlen == 0) &&
276 (sinfo->ssi_cipwlen == 0 ||
277 (sinfo->ssi_cipwlen == 1 && *sinfo->ssi_cipwd == '\0'))) {
278 user_info.lg_e_username = "anonymous";
279 user_info.lg_flags |= SMB_ATF_ANON;
280 } else {
281 user_info.lg_e_username = sinfo->ssi_user;
282 }
283
284 /*
285 * Handle user@domain format. We need to retain the original
286 * data as this is important in some forms of authentication.
287 */
288 if (*sinfo->ssi_domain == '\0') {
289 buf = smb_srm_strdup(sr, sinfo->ssi_user);
290 if ((p = strchr(buf, '@')) != NULL) {
291 *p = '\0';
292 user_info.lg_e_username = buf;
293 user_info.lg_e_domain = p + 1;
294 }
295 }
296
297 /*
298 * If no domain name has been provided in domain mode we cannot
299 * determine if this is a local user or a domain user without
300 * obtaining an access token. So we postpone the lookup until
301 * after authentication.
302 */
303 if (security == SMB_SECMODE_WORKGRP) {
304 user = smb_session_dup_user(sr->session, hostname,
305 user_info.lg_e_username);
306 } else if (*user_info.lg_e_domain != '\0') {
307 user = smb_session_dup_user(sr->session, user_info.lg_e_domain,
308 user_info.lg_e_username);
309 } else {
310 need_lookup = B_TRUE;
311 }
312
313 if (user != NULL) {
314 sinfo->ssi_guest = SMB_USER_IS_GUEST(user);
315 sr->user_cr = user->u_cred;
316 sr->smb_uid = user->u_uid;
317 sr->uid_user = user;
318 return (0);
319 }
320
321 user_info.lg_level = NETR_NETWORK_LOGON;
322 user_info.lg_domain = sinfo->ssi_domain;
323 user_info.lg_username = sinfo->ssi_user;
324 user_info.lg_workstation = sr->session->workstation;
325 user_info.lg_clnt_ipaddr = sr->session->ipaddr;
326 user_info.lg_local_ipaddr = sr->session->local_ipaddr;
327 user_info.lg_local_port = sr->session->s_local_port;
328 user_info.lg_challenge_key.val = sr->session->challenge_key;
329 user_info.lg_challenge_key.len = sr->session->challenge_len;
330 user_info.lg_nt_password.val = sinfo->ssi_cspwd;
331 user_info.lg_nt_password.len = sinfo->ssi_cspwlen;
332 user_info.lg_lm_password.val = sinfo->ssi_cipwd;
333 user_info.lg_lm_password.len = sinfo->ssi_cipwlen;
334 user_info.lg_native_os = sr->session->native_os;
335 user_info.lg_native_lm = sr->session->native_lm;
336
337 DTRACE_PROBE1(smb__sessionsetup__clntinfo, smb_logon_t *, &user_info);
338
339 if ((token = smb_get_token(&user_info)) == NULL) {
340 smbsr_error(sr, 0, ERRSRV, ERRbadpw);
341 return (-1);
342 }
343
344 if (need_lookup) {
345 user = smb_session_dup_user(sr->session,
346 token->tkn_domain_name, token->tkn_account_name);
347 if (user != NULL) {
348 sinfo->ssi_guest = SMB_USER_IS_GUEST(user);
349 sr->user_cr = user->u_cred;
350 sr->smb_uid = user->u_uid;
351 sr->uid_user = user;
352 smb_token_free(token);
353 return (0);
354 }
355 }
356
357 if (token->tkn_session_key) {
358 *session_key = smb_srm_zalloc(sr, sizeof (smb_session_key_t));
359 bcopy(token->tkn_session_key, *session_key,
360 sizeof (smb_session_key_t));
361 }
362
363 if ((cr = smb_cred_create(token)) == NULL) {
364 smb_token_free(token);
365 smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_HANDLE);
366 return (-1);
367 }
368
369 privileges = smb_priv_xlate(token);
370
371 user = smb_user_login(sr->session, cr,
372 token->tkn_domain_name, token->tkn_account_name,
373 token->tkn_flags, privileges, token->tkn_audit_sid);
374
375 crfree(cr);
376 smb_token_free(token);
377
378 if (user == NULL) {
379 smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_HANDLE);
380 return (-1);
381 }
382
383 sinfo->ssi_guest = SMB_USER_IS_GUEST(user);
384 sr->user_cr = user->u_cred;
385 sr->smb_uid = user->u_uid;
386 sr->uid_user = user;
387 return (0);
388 }
389
390 /*
391 * Allocate a Solaris cred and initialize it based on the access token.
392 *
393 * If the user can be mapped to a non-ephemeral ID, the cred gid is set
394 * to the Solaris user's primary group.
395 *
396 * If the mapped UID is ephemeral, or the primary group could not be
397 * obtained, the cred gid is set to whatever Solaris group is mapped
398 * to the token's primary group.
399 */
400 static cred_t *
smb_cred_create(smb_token_t * token)401 smb_cred_create(smb_token_t *token)
402 {
403 ksid_t ksid;
404 ksidlist_t *ksidlist = NULL;
405 smb_posix_grps_t *posix_grps;
406 cred_t *cr;
407 gid_t gid;
408
409 ASSERT(token);
410 ASSERT(token->tkn_posix_grps);
411 posix_grps = token->tkn_posix_grps;
412
413 cr = crget();
414 ASSERT(cr != NULL);
415
416 if (!IDMAP_ID_IS_EPHEMERAL(token->tkn_user.i_id) &&
417 (posix_grps->pg_ngrps != 0)) {
418 gid = posix_grps->pg_grps[0];
419 } else {
420 gid = token->tkn_primary_grp.i_id;
421 }
422
423 if (crsetugid(cr, token->tkn_user.i_id, gid) != 0) {
424 crfree(cr);
425 return (NULL);
426 }
427
428 if (crsetgroups(cr, posix_grps->pg_ngrps, posix_grps->pg_grps) != 0) {
429 crfree(cr);
430 return (NULL);
431 }
432
433 smb_cred_set_sid(&token->tkn_user, &ksid);
434 crsetsid(cr, &ksid, KSID_USER);
435 smb_cred_set_sid(&token->tkn_primary_grp, &ksid);
436 crsetsid(cr, &ksid, KSID_GROUP);
437 smb_cred_set_sid(&token->tkn_owner, &ksid);
438 crsetsid(cr, &ksid, KSID_OWNER);
439 ksidlist = smb_cred_set_sidlist(&token->tkn_win_grps);
440 crsetsidlist(cr, ksidlist);
441
442 if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID))
443 (void) crsetpriv(cr, PRIV_FILE_CHOWN, NULL);
444
445 return (cr);
446 }
447
448 /*
449 * Initialize the ksid based on the given smb_id_t.
450 */
451 static void
smb_cred_set_sid(smb_id_t * id,ksid_t * ksid)452 smb_cred_set_sid(smb_id_t *id, ksid_t *ksid)
453 {
454 char sidstr[SMB_SID_STRSZ];
455 int rc;
456
457 ASSERT(id);
458 ASSERT(id->i_sid);
459
460 ksid->ks_id = id->i_id;
461 smb_sid_tostr(id->i_sid, sidstr);
462 rc = smb_sid_splitstr(sidstr, &ksid->ks_rid);
463 ASSERT(rc == 0);
464
465 ksid->ks_attr = id->i_attrs;
466 ksid->ks_domain = ksid_lookupdomain(sidstr);
467 }
468
469 /*
470 * Allocate and initialize the ksidlist based on the access token group list.
471 */
472 static ksidlist_t *
smb_cred_set_sidlist(smb_ids_t * token_grps)473 smb_cred_set_sidlist(smb_ids_t *token_grps)
474 {
475 int i;
476 ksidlist_t *lp;
477
478 lp = kmem_zalloc(KSIDLIST_MEM(token_grps->i_cnt), KM_SLEEP);
479 lp->ksl_ref = 1;
480 lp->ksl_nsid = token_grps->i_cnt;
481 lp->ksl_neid = 0;
482
483 for (i = 0; i < lp->ksl_nsid; i++) {
484 smb_cred_set_sid(&token_grps->i_ids[i], &lp->ksl_sids[i]);
485 if (lp->ksl_sids[i].ks_id > IDMAP_WK__MAX_GID)
486 lp->ksl_neid++;
487 }
488
489 return (lp);
490 }
491
492 /*
493 * Convert access token privileges to local definitions.
494 */
495 static uint32_t
smb_priv_xlate(smb_token_t * token)496 smb_priv_xlate(smb_token_t *token)
497 {
498 uint32_t privileges = 0;
499
500 if (smb_token_query_privilege(token, SE_BACKUP_LUID))
501 privileges |= SMB_USER_PRIV_BACKUP;
502
503 if (smb_token_query_privilege(token, SE_RESTORE_LUID))
504 privileges |= SMB_USER_PRIV_RESTORE;
505
506 if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID))
507 privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP;
508
509 if (smb_token_query_privilege(token, SE_SECURITY_LUID))
510 privileges |= SMB_USER_PRIV_SECURITY;
511
512 return (privileges);
513 }
514