/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include #include #include #include #include #include #include #include smb_sdrc_t smb_pre_session_setup_andx(smb_request_t *sr) { smb_arg_sessionsetup_t *sinfo; char *native_os; char *native_lm; int rc = 0; sinfo = smb_srm_zalloc(sr, sizeof (smb_arg_sessionsetup_t)); sr->sr_ssetup = sinfo; /* * Enforce the minimum word count seen in the old protocol, * to make sure we have enough to decode the common stuff. * Further wcnt checks below. */ if (sr->smb_wct < 10) { rc = -1; goto done; } /* * Parse common part of SMB session setup. * skip: vcnumber(2), sesskey(4) */ rc = smbsr_decode_vwv(sr, "b.www6.", &sr->andx_com, &sr->andx_off, &sinfo->ssi_maxbufsize, &sinfo->ssi_maxmpxcount); if (rc != 0) goto done; if (sr->session->dialect < NT_LM_0_12) { sinfo->ssi_type = SMB_SSNSETUP_PRE_NTLM012; sinfo->ssi_capabilities = 0; rc = smbsr_decode_vwv(sr, "w4.", &sinfo->ssi_lmpwlen); if (rc != 0) goto done; sinfo->ssi_lmpwd = smb_srm_zalloc(sr, sinfo->ssi_lmpwlen + 1); rc = smbsr_decode_data(sr, "%#c", sr, sinfo->ssi_lmpwlen, sinfo->ssi_lmpwd); if (rc != 0) goto done; sinfo->ssi_lmpwd[sinfo->ssi_lmpwlen] = 0; if (smbsr_decode_data(sr, "%u", sr, &sinfo->ssi_user) != 0) sinfo->ssi_user = ""; if (smbsr_decode_data(sr, "%u", sr, &sinfo->ssi_domain) != 0) sinfo->ssi_domain = ""; goto part2; } /* * We have dialect >= NT_LM_0_12 */ if (sr->smb_wct == 13) { /* Old style (non-extended) request. */ sinfo->ssi_type = SMB_SSNSETUP_NTLM012_NOEXT; rc = smbsr_decode_vwv(sr, "ww4.l", &sinfo->ssi_lmpwlen, &sinfo->ssi_ntpwlen, &sinfo->ssi_capabilities); if (rc != 0) goto done; /* paranoid: ignore cap. ext. sec. here */ sinfo->ssi_capabilities &= ~CAP_EXTENDED_SECURITY; sinfo->ssi_lmpwd = smb_srm_zalloc(sr, sinfo->ssi_lmpwlen + 1); sinfo->ssi_ntpwd = smb_srm_zalloc(sr, sinfo->ssi_ntpwlen + 1); rc = smbsr_decode_data(sr, "%#c#cuu", sr, sinfo->ssi_lmpwlen, sinfo->ssi_lmpwd, sinfo->ssi_ntpwlen, sinfo->ssi_ntpwd, &sinfo->ssi_user, &sinfo->ssi_domain); if (rc != 0) goto done; sinfo->ssi_lmpwd[sinfo->ssi_lmpwlen] = 0; sinfo->ssi_ntpwd[sinfo->ssi_ntpwlen] = 0; goto part2; } if (sr->smb_wct == 12) { /* New style (extended) request. */ sinfo->ssi_type = SMB_SSNSETUP_NTLM012_EXTSEC; rc = smbsr_decode_vwv(sr, "w4.l", &sinfo->ssi_iseclen, &sinfo->ssi_capabilities); if (rc != 0) goto done; if ((sinfo->ssi_capabilities & CAP_EXTENDED_SECURITY) == 0) { rc = -1; goto done; } sinfo->ssi_isecblob = smb_srm_zalloc(sr, sinfo->ssi_iseclen); rc = smbsr_decode_data(sr, "%#c", sr, sinfo->ssi_iseclen, sinfo->ssi_isecblob); if (rc != 0) goto done; goto part2; } /* Invalid message */ rc = -1; goto done; part2: /* * Get the "Native OS" and "Native LanMan" strings. * These are not critical to protocol function, so * if we can't parse them, just guess "NT". * These strings are free'd with the sr. * * In NTLM 0.12, the padding between the Native OS and Native LM * is a bit strange. On NT4.0, there is a 2 byte pad between the * OS (Windows NT 1381) and LM (Windows NT 4.0). On Windows 2000, * there is no padding between the OS (Windows 2000 2195) and LM * (Windows 2000 5.0). If the padding is removed from the decode * string the NT4.0 LM comes out as an empty string. So if the * client's native OS is Win NT, assume extra padding. */ rc = smbsr_decode_data(sr, "%u", sr, &native_os); if (rc != 0 || native_os == NULL) sinfo->ssi_native_os = NATIVE_OS_WINNT; else sinfo->ssi_native_os = smbnative_os_value(native_os); if (sinfo->ssi_native_os == NATIVE_OS_WINNT) rc = smbsr_decode_data(sr, "%,u", sr, &native_lm); else rc = smbsr_decode_data(sr, "%u", sr, &native_lm); if (rc != 0 || native_lm == NULL) sinfo->ssi_native_lm = NATIVE_LM_NT; else sinfo->ssi_native_lm = smbnative_lm_value(native_lm); rc = 0; done: if (rc != 0) { cmn_err(CE_NOTE, "SmbSessonSetupX: client %s invalid request", sr->session->ip_addr_str); } DTRACE_SMB_START(op__SessionSetupX, smb_request_t *, sr); return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } void smb_post_session_setup_andx(smb_request_t *sr) { smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup; DTRACE_SMB_DONE(op__SessionSetupX, smb_request_t *, sr); if (sinfo->ssi_lmpwd != NULL) bzero(sinfo->ssi_lmpwd, sinfo->ssi_lmpwlen); if (sinfo->ssi_ntpwd != NULL) bzero(sinfo->ssi_ntpwd, sinfo->ssi_ntpwlen); } /* * * NT systems use different native OS and native LanMan values dependent on * whether they are acting as a client or a server. NT 4.0 server responds * with the following values: * * NativeOS: Windows NT 4.0 * NativeLM: NT LAN Manager 4.0 */ smb_sdrc_t smb_com_session_setup_andx(smb_request_t *sr) { smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup; uint32_t status; uint16_t action; int rc; /* * Some stuff we do only in the first in a (possible) * sequence of session setup requests. */ if (sinfo->ssi_type != SMB_SSNSETUP_NTLM012_EXTSEC || sr->smb_uid == 0 || sr->smb_uid == 0xFFFF) { /* This is a first (or only) call */ sr->session->smb_msg_size = sinfo->ssi_maxbufsize; sr->session->smb_max_mpx = sinfo->ssi_maxmpxcount; sr->session->capabilities = sinfo->ssi_capabilities; sr->session->native_os = sinfo->ssi_native_os; sr->session->native_lm = sinfo->ssi_native_lm; } /* RejectUnencryptedAccess precludes SMB1 access */ if (sr->sr_server->sv_cfg.skc_encrypt == SMB_CONFIG_REQUIRED) { smbsr_error(sr, NT_STATUS_ACCESS_DENIED, ERRDOS, ERROR_ACCESS_DENIED); return (SDRC_ERROR); } /* * The "meat" of authentication happens here. */ if (sinfo->ssi_type == SMB_SSNSETUP_NTLM012_EXTSEC) status = smb_authenticate_ext(sr); else status = smb_authenticate_old(sr); switch (status) { case NT_STATUS_SUCCESS: break; /* * This is not really an error, but tells the client * it should send another session setup request. */ case NT_STATUS_MORE_PROCESSING_REQUIRED: smbsr_error(sr, status, 0, 0); break; case NT_STATUS_ACCESS_DENIED: smbsr_error(sr, status, ERRDOS, ERROR_ACCESS_DENIED); return (SDRC_ERROR); case NT_STATUS_TOO_MANY_SESSIONS: smbsr_error(sr, status, ERRSRV, ERRtoomanyuids); return (SDRC_ERROR); case NT_STATUS_NO_LOGON_SERVERS: smbsr_error(sr, status, ERRDOS, ERROR_NO_LOGON_SERVERS); return (SDRC_ERROR); case NT_STATUS_NETLOGON_NOT_STARTED: smbsr_error(sr, status, ERRDOS, ERROR_NETLOGON_NOT_STARTED); return (SDRC_ERROR); case NT_STATUS_USER_SESSION_DELETED: smbsr_error(sr, status, ERRSRV, ERRbaduid); return (SDRC_ERROR); case NT_STATUS_INSUFF_SERVER_RESOURCES: smbsr_error(sr, status, ERRSRV, ERRnoresource); return (SDRC_ERROR); case NT_STATUS_INTERNAL_ERROR: default: smbsr_error(sr, status, ERRSRV, ERRsrverror); return (SDRC_ERROR); } action = SMB_USER_IS_GUEST(sr->uid_user) ? 1 : 0; switch (sinfo->ssi_type) { default: case SMB_SSNSETUP_PRE_NTLM012: case SMB_SSNSETUP_NTLM012_NOEXT: rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.www%uuu", 3, sr->andx_com, -1, /* andx_off */ action, VAR_BCC, sr, sr->sr_cfg->skc_native_os, sr->sr_cfg->skc_native_lm, sr->sr_cfg->skc_nbdomain); break; case SMB_SSNSETUP_NTLM012_EXTSEC: rc = smbsr_encode_result(sr, 4, VAR_BCC, "bb.wwww%#cuuu", 4, sr->andx_com, -1, /* andx_off */ action, sinfo->ssi_oseclen, VAR_BCC, sr, sinfo->ssi_oseclen, sinfo->ssi_osecblob, sr->sr_cfg->skc_native_os, sr->sr_cfg->skc_native_lm, sr->sr_cfg->skc_nbdomain); break; } return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); }