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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 #pragma ident "@(#)smb_session_setup_andx.c 1.6 08/07/08 SMI" 26 /* 27 * SMB: session_setup_andx 28 * 29 * This SMB is used to further "Set up" the session normally just 30 * established via the negotiate protocol. 31 * 32 * One primary function is to perform a "user logon" in the case where the 33 * server is in user level security mode. The Uid in the SMB header is set 34 * by the client to be the userid desired for the AccountName and validated 35 * by the AccountPassword. 36 * 37 * If the negotiated protocol is prior to NT LM 0.12, the format of 38 * SMB_COM_SESSION_SETUP_ANDX is: 39 * 40 * Client Request Description 41 * ============================== ===================================== 42 * 43 * UCHAR WordCount; Count of parameter words = 10 44 * UCHAR AndXCommand; Secondary (X) command; 0xFF = none 45 * UCHAR AndXReserved; Reserved (must be 0) 46 * USHORT AndXOffset; Offset to next command WordCount 47 * USHORT MaxBufferSize; Client maximum buffer size 48 * USHORT MaxMpxCount; Actual maximum multiplexed pending 49 * requests 50 * USHORT VcNumber; 0 = first (only), nonzero=additional 51 * VC number 52 * ULONG SessionKey; Session key (valid iff VcNumber != 0) 53 * USHORT PasswordLength; Account password size 54 * ULONG Reserved; Must be 0 55 * USHORT ByteCount; Count of data bytes; min = 0 56 * UCHAR AccountPassword[]; Account Password 57 * STRING AccountName[]; Account Name 58 * STRING PrimaryDomain[]; Client's primary domain 59 * STRING NativeOS[]; Client's native operating system 60 * STRING NativeLanMan[]; Client's native LAN Manager type 61 * 62 * and the response is: 63 * 64 * Server Response Description 65 * ================================== ================================= 66 * 67 * UCHAR WordCount; Count of parameter words = 3 68 * UCHAR AndXCommand; Secondary (X) command; 0xFF = 69 * none 70 * UCHAR AndXReserved; Reserved (must be 0) 71 * USHORT AndXOffset; Offset to next command WordCount 72 * USHORT Action; Request mode: 73 * bit0 = logged in as GUEST 74 * USHORT ByteCount; Count of data bytes 75 * STRING NativeOS[]; Server's native operating system 76 * STRING NativeLanMan[]; Server's native LAN Manager type 77 * STRING PrimaryDomain[]; Server's primary domain 78 * 79 * If the server is in "share level security mode", the account name and 80 * passwd should be ignored by the server. 81 * 82 * If challenge/response authentication is not being used, AccountPassword 83 * should be a null terminated ASCII string with PasswordLength set to the 84 * string size including the null; the password will case insensitive. If 85 * challenge/response authentication is being used (see section 2.10), then 86 * AccountPassword will be the response to the server's challenge, and 87 * PasswordLength should be set to its length. 88 * 89 * The server validates the name and password supplied and if valid, it 90 * registers the user identifier on this session as representing the 91 * specified AccountName. The Uid field in the SMB header will then be 92 * used to validate access on subsequent SMB requests. The SMB requests 93 * where permission checks are required are those which refer to a 94 * symbolically named resource such as SMB_COM_OPEN, SMB_COM_RENAME, 95 * SMB_COM_DELETE, etc.. The value of the Uid is relative to a specific 96 * client/server session so it is possible to have the same Uid value 97 * represent two different users on two different sessions at the server. 98 * 99 * Multiple session setup commands may be sent to register additional users 100 * on this session. If the server receives an additional 101 * SMB_COM_SESSION_SETUP_ANDX, only the Uid, AccountName and 102 * AccountPassword fields need contain valid values (the server MUST ignore 103 * the other fields). 104 * 105 * The client writes the name of its domain in PrimaryDomain if it knows 106 * what the domain name is. If the domain name is unknown, the client 107 * either encodes it as a NULL string, or as a question mark. 108 * 109 * If bit0 of Action is set, this informs the client that although the 110 * server did not recognize the AccountName, it logged the user in as a 111 * guest. This is optional behavior by the server, and in any case one 112 * would ordinarily expect guest privileges to limited. 113 * 114 * Another function of the Session Set Up protocol is to inform the server 115 * of the maximum values which will be utilized by this client. Here 116 * MaxBufferSize is the maximum message size which the client can receive. 117 * Thus although the server may support 16k buffers (as returned in the 118 * SMB_COM_NEGOTIATE response), if the client only has 4k buffers, the 119 * value of MaxBufferSize here would be 4096. The minimum allowable value 120 * for MaxBufferSize is 1024. The SMB_COM_NEGOTIATE response includes the 121 * server buffer size supported. Thus this is the maximum SMB message size 122 * which the client can send to the server. This size may be larger than 123 * the size returned to the server from the client via the 124 * SMB_COM_SESSION_SETUP_AND X protocol which is the maximum SMB message 125 * size which the server may send to the client. Thus if the server's 126 * buffer size were 4k and the client's buffer size were only 2K, the 127 * client could send up to 4k (standard) write requests but must only 128 * request up to 2k for (standard) read requests. 129 * 130 * The field, MaxMpxCount informs the server of the maximum number of 131 * requests which the client will have outstanding to the server 132 * simultaneously (see sections 5.13 and 5.25). 133 * 134 * The VcNumber field specifies whether the client wants this to be the 135 * first VC or an additional VC. If the the SMB_COM_SESSION_SETUP_ANDX 136 * request contains a VcNumber of 0 and other VCs are still connected to 137 * that client, they should be aborted to free any resources held by the 138 * server. This condition could occur if the client was rebooted and 139 * reconnected to the server before the transport level had informed the 140 * server of the previous VC termination. There is more information on 141 * VCs in smb_negotiate.c. 142 * 143 * The values for MaxBufferSize, MaxMpxCount, and VcNumber must be less 144 * than or equal to the maximum values supported by the server as returned 145 * in the SMB_COM_NEGOTIATE response. 146 * 147 * If the negotiated SMB dialect is "NT LM 0.12" or later, the format of 148 * the response SMB is unchanged, but the request is: 149 * 150 * Client Request Description 151 * ============================== ===================================== 152 * 153 * UCHAR WordCount; Count of parameter words = 13 154 * UCHAR AndXCommand; Secondary (X) command; 0xFF = none 155 * UCHAR AndXReserved; Reserved (must be 0) 156 * USHORT AndXOffset; Offset to next command WordCount 157 * USHORT MaxBufferSize; Client's maximum buffer size 158 * USHORT MaxMpxCount; Actual maximum multiplexed pending 159 * requests 160 * USHORT VcNumber; 0 = first (only), nonzero=additional 161 * VC number 162 * ULONG SessionKey; Session key (valid iff VcNumber != 0) 163 * USHORT Account password size, ANSI 164 * CaseInsensitivePasswordLength; 165 * USHORT Account password size, Unicode 166 * CaseSensitivePasswordLength; 167 * ULONG Reserved; must be 0 168 * ULONG Capabilities; Client capabilities 169 * USHORT ByteCount; Count of data bytes; min = 0 170 * UCHAR Account Password, ANSI 171 * CaseInsensitivePassword[]; 172 * UCHAR CaseSensitivePassword[]; Account Password, Unicode 173 * STRING AccountName[]; Account Name, Unicode 174 * STRING PrimaryDomain[]; Client's primary domain, Unicode 175 * STRING NativeOS[]; Client's native operating system, 176 * Unicode 177 * STRING NativeLanMan[]; Client's native LAN Manager type, 178 * Unicode 179 * 180 * The client expresses its capabilities to the server encoded in the 181 * Capabilities field: 182 * 183 * Capability Name Encoding Description 184 * ======================== ========= ================================ 185 * 186 * CAP_UNICODE 0x0004 The client can use UNICODE 187 * strings 188 * CAP_LARGE_FILES 0x0008 The client can deal with files 189 * having 64 bit offsets 190 * CAP_NT_SMBS 0x0010 The client understands the SMBs 191 * introduced with the NT LM 0.12 192 * dialect. Implies CAP_NT_FIND. 193 * CAP_NT_FIND 0x0200 194 * CAP_STATUS32 0x0040 The client can receive 32 bit 195 * errors encoded in Status.Status 196 * CAP_LEVEL_II_OPLOCKS 0x0080 The client understands Level II 197 * oplocks 198 * 199 * The entire message sent and received including the optional ANDX SMB 200 * must fit in the negotiated maximum transfer size. The following are the 201 * only valid SMB commands for AndXCommand for SMB_COM_SESSION_SETUP_ANDX 202 * 203 * SMB_COM_TREE_CONNECT_ANDX SMB_COM_OPEN 204 * SMB_COM_OPEN_ANDX SMB_COM_CREATE 205 * SMB_COM_CREATE_NEW SMB_COM_CREATE_DIRECTORY 206 * SMB_COM_DELETE SMB_COM_DELETE_DIRECTORY 207 * SMB_COM_FIND SMB_COM_FIND_UNIQUE 208 * SMB_COM_COPY SMB_COM_RENAME 209 * SMB_COM_NT_RENAME SMB_COM_CHECK_DIRECTORY 210 * SMB_COM_QUERY_INFORMATION SMB_COM_SET_INFORMATION 211 * SMB_COM_NO_ANDX_COMMAND SMB_COM_OPEN_PRINT_FILE 212 * SMB_COM_GET_PRINT_QUEUE SMB_COM_TRANSACTION 213 * 214 * 4.1.2.1 Errors 215 * 216 * ERRSRV/ERRerror - no NEG_PROT issued 217 * ERRSRV/ERRbadpw - password not correct for given user name 218 * ERRSRV/ERRtoomanyuids - maximum number of users per session exceeded 219 * ERRSRV/ERRnosupport - chaining of this request to the previous one is 220 * not supported 221 */ 222 223 #include <sys/types.h> 224 #include <sys/socket.h> 225 #include <netinet/in.h> 226 #include <smbsrv/smb_incl.h> 227 #include <smbsrv/smb_token.h> 228 #include <smbsrv/smb_door_svc.h> 229 230 smb_sdrc_t 231 smb_pre_session_setup_andx(smb_request_t *sr) 232 { 233 DTRACE_SMB_1(op__SessionSetupX__start, smb_request_t *, sr); 234 return (SDRC_SUCCESS); 235 } 236 237 void 238 smb_post_session_setup_andx(smb_request_t *sr) 239 { 240 DTRACE_SMB_1(op__SessionSetupX__done, smb_request_t *, sr); 241 } 242 243 smb_sdrc_t 244 smb_com_session_setup_andx(smb_request_t *sr) 245 { 246 uint16_t maxbufsize, maxmpxcount, vcnumber = 0; 247 uint32_t sesskey; 248 uint32_t capabilities = 0; 249 char *account_name = ""; 250 char *primary_domain = ""; 251 char *native_os = ""; 252 char *native_lanman = ""; 253 char *hostname = sr->sr_cfg->skc_hostname; 254 smb_token_t *usr_token = NULL; 255 smb_user_t *user = NULL; 256 int security = sr->sr_cfg->skc_secmode; 257 258 uint16_t ci_pwlen = 0; 259 unsigned char *ci_password = NULL; 260 uint16_t cs_pwlen = 0; 261 unsigned char *cs_password = NULL; 262 263 netr_client_t clnt_info; 264 smb_session_key_t *session_key = NULL; 265 int rc; 266 char ipaddr_buf[INET6_ADDRSTRLEN]; 267 268 if (sr->session->dialect >= NT_LM_0_12) { 269 rc = smbsr_decode_vwv(sr, "b.wwwwlww4.l", &sr->andx_com, 270 &sr->andx_off, &maxbufsize, &maxmpxcount, &vcnumber, 271 &sesskey, &ci_pwlen, &cs_pwlen, &capabilities); 272 273 if (rc != 0) 274 return (SDRC_ERROR); 275 276 ci_password = kmem_alloc(ci_pwlen + 1, KM_SLEEP); 277 cs_password = kmem_alloc(cs_pwlen + 1, KM_SLEEP); 278 279 /* 280 * The padding between the Native OS and Native LM is a 281 * bit strange. On NT4.0, there is a 2 byte pad between 282 * the OS (Windows NT 1381) and LM (Windows NT 4.0). 283 * On Windows 2000, there is no padding between the OS 284 * (Windows 2000 2195) and LM (Windows 2000 5.0). 285 * 286 * If the padding is removed from this decode string 287 * the NT4.0 LM comes out as an empty string. 288 * 289 * So if the client's native OS is Win NT we consider 290 * the padding otherwise we don't. 291 */ 292 rc = smbsr_decode_data(sr, "%#c#cuuu", 293 sr, 294 ci_pwlen, ci_password, 295 cs_pwlen, cs_password, 296 &account_name, 297 &primary_domain, 298 &native_os); 299 300 if (rc != 0) { 301 kmem_free(ci_password, ci_pwlen + 1); 302 kmem_free(cs_password, cs_pwlen + 1); 303 return (SDRC_ERROR); 304 } 305 306 ci_password[ci_pwlen] = 0; 307 cs_password[cs_pwlen] = 0; 308 309 sr->session->native_os = smbnative_os_value(native_os); 310 311 if (sr->session->native_os == NATIVE_OS_WINNT) 312 rc = smbsr_decode_data(sr, "%,u", sr, &native_lanman); 313 else 314 rc = smbsr_decode_data(sr, "%u", sr, &native_lanman); 315 316 /* 317 * Native Lanman could be null so we really don't care 318 * if above decode fails, but to have a valid value for 319 * the field we set it to Win NT. 320 */ 321 if (rc != 0) 322 native_lanman = "NT LAN Manager 4.0"; 323 324 } else { 325 rc = smbsr_decode_vwv(sr, "b.wwwwlw4.", &sr->andx_com, 326 &sr->andx_off, &maxbufsize, &maxmpxcount, 327 &vcnumber, &sesskey, &ci_pwlen); 328 329 if (rc != 0) 330 return (SDRC_ERROR); 331 332 ci_password = kmem_alloc(ci_pwlen + 1, KM_SLEEP); 333 rc = smbsr_decode_data(sr, "%#c", sr, ci_pwlen, ci_password); 334 if (rc != 0) { 335 kmem_free(ci_password, ci_pwlen + 1); 336 return (SDRC_ERROR); 337 } 338 339 ci_password[ci_pwlen] = 0; 340 341 /* 342 * Despite the CIFS/1.0 spec, the rest of this message is 343 * not always present. We need to try to get the account 344 * name and the primary domain but we don't care about the 345 * the native OS or native LanMan fields. 346 */ 347 if (smbsr_decode_data(sr, "%u", sr, &account_name) != 0) 348 account_name = ""; 349 350 if (smbsr_decode_data(sr, "%u", sr, &primary_domain) != 0) 351 primary_domain = ""; 352 353 sr->session->native_os = NATIVE_OS_UNKNOWN; 354 } 355 356 /* 357 * If the vcnumber is zero, we can discard any 358 * other connections associated with this client. 359 */ 360 sr->session->vcnumber = vcnumber; 361 if (vcnumber == 0) 362 smb_server_reconnection_check(sr->sr_server, sr->session); 363 364 sr->session->smb_msg_size = maxbufsize; 365 366 bzero(&clnt_info, sizeof (netr_client_t)); 367 368 if (*primary_domain == 0) 369 primary_domain = sr->sr_cfg->skc_resource_domain; 370 371 if ((cs_pwlen == 0) && 372 (ci_pwlen == 0 || (ci_pwlen == 1 && *ci_password == 0))) { 373 /* anonymous user */ 374 clnt_info.flags |= NETR_CFLG_ANON; 375 account_name = "nobody"; 376 } else if (*account_name == '\0') { 377 if (ci_password) 378 kmem_free(ci_password, ci_pwlen + 1); 379 if (cs_password) 380 kmem_free(cs_password, cs_pwlen + 1); 381 smbsr_error(sr, 0, ERRSRV, ERRaccess); 382 return (SDRC_ERROR); 383 } else if (utf8_strcasecmp(primary_domain, hostname) == 0) { 384 /* 385 * When domain name is equal to hostname, it means 386 * the user is local even if system is running in 387 * domain mode, so perform a local logon. 388 */ 389 clnt_info.flags |= NETR_CFLG_LOCAL; 390 } else if (security == SMB_SECMODE_DOMAIN) { 391 clnt_info.flags |= NETR_CFLG_DOMAIN; 392 } else if (security == SMB_SECMODE_WORKGRP) { 393 clnt_info.flags |= NETR_CFLG_LOCAL; 394 } 395 396 /* 397 * If this is an additional setup for an existing user 398 * on this session, duplicate the authenticated user. 399 * Otherwise authenticate as new user. 400 */ 401 user = smb_user_lookup_by_name(sr->session, primary_domain, 402 account_name); 403 404 if (user) { 405 smb_user_t *orig_user = user; 406 407 user = smb_user_dup(orig_user); 408 smb_user_release(orig_user); 409 } else { 410 cred_t *cr; 411 uint32_t privileges; 412 413 clnt_info.logon_level = NETR_NETWORK_LOGON; 414 clnt_info.domain = primary_domain; 415 clnt_info.username = account_name; 416 clnt_info.workstation = sr->session->workstation; 417 clnt_info.ipaddr = sr->session->ipaddr; 418 clnt_info.local_ipaddr = sr->session->local_ipaddr; 419 clnt_info.challenge_key.challenge_key_val = 420 sr->session->challenge_key; 421 clnt_info.challenge_key.challenge_key_len = 422 sr->session->challenge_len; 423 clnt_info.nt_password.nt_password_val = cs_password; 424 clnt_info.nt_password.nt_password_len = cs_pwlen; 425 clnt_info.lm_password.lm_password_val = ci_password; 426 clnt_info.lm_password.lm_password_len = ci_pwlen; 427 clnt_info.native_os = sr->session->native_os; 428 clnt_info.native_lm = smbnative_lm_value(native_lanman); 429 clnt_info.local_port = sr->session->s_local_port; 430 431 DTRACE_PROBE1(smb__sessionsetup__clntinfo, netr_client_t *, 432 &clnt_info); 433 434 usr_token = smb_upcall_get_token(&clnt_info); 435 if (usr_token == 0) { 436 if (ci_password) 437 kmem_free(ci_password, ci_pwlen + 1); 438 if (cs_password) 439 kmem_free(cs_password, cs_pwlen + 1); 440 smbsr_error(sr, 0, ERRSRV, ERRbadpw); 441 return (SDRC_ERROR); 442 } 443 444 if (usr_token->tkn_session_key) { 445 session_key = kmem_alloc(sizeof (smb_session_key_t), 446 KM_SLEEP); 447 (void) memcpy(session_key, usr_token->tkn_session_key, 448 sizeof (smb_session_key_t)); 449 } 450 451 cr = smb_cred_create(usr_token, &privileges); 452 if (cr != NULL) { 453 user = smb_user_login(sr->session, cr, 454 usr_token->tkn_domain_name, 455 usr_token->tkn_account_name, 456 usr_token->tkn_flags, 457 privileges, 458 usr_token->tkn_audit_sid); 459 smb_cred_rele(cr); 460 } 461 smb_token_free(usr_token); 462 } 463 464 if (ci_password) 465 kmem_free(ci_password, ci_pwlen + 1); 466 467 if (user == NULL) { 468 if (session_key) 469 kmem_free(session_key, sizeof (smb_session_key_t)); 470 if (cs_password) 471 kmem_free(cs_password, cs_pwlen + 1); 472 smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_HANDLE); 473 return (SDRC_ERROR); 474 } 475 476 sr->user_cr = user->u_cred; 477 sr->smb_uid = user->u_uid; 478 sr->uid_user = user; 479 sr->session->capabilities = capabilities; 480 481 /* 482 * Check to see if SMB signing is enable, but if it is already turned 483 * on leave it. 484 * The first authenticated logon provides the MAC key and sequence 485 * numbers for signing all further session on the 486 * same network connection. 487 */ 488 if (!(sr->session->signing.flags & SMB_SIGNING_ENABLED) && 489 (sr->session->secmode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) && 490 (sr->smb_flg2 & SMB_FLAGS2_SMB_SECURITY_SIGNATURE) && 491 session_key) 492 smb_sign_init(sr, session_key, (char *)cs_password, cs_pwlen); 493 494 if (cs_password) 495 kmem_free(cs_password, cs_pwlen + 1); 496 497 if (session_key) 498 kmem_free(session_key, sizeof (smb_session_key_t)); 499 500 if (!(sr->smb_flg2 & SMB_FLAGS2_SMB_SECURITY_SIGNATURE) && 501 (sr->sr_cfg->skc_signing_required)) { 502 (void) inet_ntop(AF_INET, (char *)&sr->session->ipaddr, 503 ipaddr_buf, sizeof (ipaddr_buf)); 504 cmn_err(CE_NOTE, 505 "SmbSessonSetupX: client %s is not capable of signing", 506 ipaddr_buf); 507 smbsr_error(sr, NT_STATUS_LOGON_FAILURE, 508 ERRDOS, ERROR_LOGON_FAILURE); 509 return (SDRC_ERROR); 510 } 511 512 /* 513 * NT systems use different native OS and native LanMan values 514 * dependent on whether they are acting as a client or a server. 515 * As a server, NT 4.0 responds with the following values: 516 * 517 * NativeOS: Windows NT 4.0 518 * NativeLM: NT LAN Manager 4.0 519 * 520 * We should probably use the same values as NT but this code has 521 * been using the product name and "Windows NT 4.0" for a long time 522 * and I don't know if a change would cause any problems (see the 523 * conditional test below). 524 */ 525 rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.www%uuu", 526 3, 527 sr->andx_com, 528 -1, /* andx_off */ 529 ((user->u_flags & SMB_USER_FLAG_GUEST) ? 1 : 0), 530 VAR_BCC, 531 sr, 532 "Windows NT 4.0", 533 "NT LAN Manager 4.0", 534 sr->sr_cfg->skc_resource_domain); 535 536 return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); 537 } 538