Line data Source code
1 : /* 2 : * Copyright (c) 2020 Andreas Schneider <asn@samba.org> 3 : * 4 : * This program is free software: you can redistribute it and/or modify 5 : * it under the terms of the GNU General Public License as published by 6 : * the Free Software Foundation, either version 3 of the License, or 7 : * (at your option) any later version. 8 : * 9 : * This program is distributed in the hope that it will be useful, 10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 : * GNU General Public License for more details. 13 : * 14 : * You should have received a copy of the GNU General Public License 15 : * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 : */ 17 : 18 : #include "includes.h" 19 : #include "librpc/gen_ndr/security.h" 20 : #include "librpc/gen_ndr/auth.h" 21 : #include "lib/crypto/gnutls_helpers.h" 22 : #include "libcli/security/dom_sid.h" 23 : #include "libcli/security/security_token.h" 24 : #include "libcli/smb/smb2_constants.h" 25 : 26 : #include "dcerpc_helper.h" 27 : 28 3 : static bool smb3_sid_parse(const struct dom_sid *sid, 29 : uint16_t *pdialect, 30 : uint16_t *pencrypt, 31 : uint16_t *pcipher) 32 : { 33 0 : uint16_t dialect; 34 0 : uint16_t encrypt; 35 0 : uint16_t cipher; 36 : 37 3 : if (sid->sub_auths[0] != global_sid_Samba_SMB3.sub_auths[0]) { 38 0 : return false; 39 : } 40 : 41 3 : dialect = sid->sub_auths[1]; 42 3 : if (dialect > 0x03ff) { 43 0 : return false; 44 : } 45 : 46 3 : encrypt = sid->sub_auths[2]; 47 3 : if (encrypt > 0x0002) { 48 0 : return false; 49 : } 50 : 51 3 : cipher = sid->sub_auths[3]; 52 3 : if (cipher > 256) { 53 : /* 54 : * It is unlikely that we 55 : * ever have more then 256 56 : * encryption algorithms 57 : */ 58 0 : return false; 59 : } 60 : 61 3 : if (pdialect != NULL) { 62 3 : *pdialect = dialect; 63 : } 64 : 65 3 : if (pencrypt != NULL) { 66 3 : *pencrypt = encrypt; 67 : } 68 : 69 3 : if (pcipher != NULL) { 70 3 : *pcipher = cipher; 71 : } 72 : 73 3 : return true; 74 : } 75 : 76 1236 : bool dcerpc_is_transport_encrypted(struct auth_session_info *session_info) 77 : { 78 1236 : struct security_token *token = session_info->security_token; 79 1236 : struct dom_sid smb3_dom_sid = global_sid_Samba_SMB3; 80 1236 : const struct dom_sid *smb3_sid = NULL; 81 1236 : uint16_t dialect = 0; 82 1236 : uint16_t encrypt = 0; 83 1236 : uint16_t cipher = 0; 84 72 : size_t num_smb3_sids; 85 72 : bool ok; 86 : 87 1236 : num_smb3_sids = security_token_count_flag_sids(token, 88 : &smb3_dom_sid, 89 : 3, 90 : &smb3_sid); 91 1236 : if (num_smb3_sids > 1) { 92 0 : DBG_ERR("ERROR: The SMB3 SID has been detected %zu times\n", 93 : num_smb3_sids); 94 0 : return false; 95 : } 96 : 97 1236 : if (smb3_sid == NULL) { 98 1161 : return false; 99 : } 100 : 101 3 : ok = smb3_sid_parse(smb3_sid, &dialect, &encrypt, &cipher); 102 3 : if (!ok) { 103 0 : DBG_ERR("Failed to parse SMB3 SID!\n"); 104 0 : return false; 105 : } 106 : 107 3 : DBG_DEBUG("SMB SID - dialect: %#04x, encrypt: %#04x, cipher: %#04x\n", 108 : dialect, 109 : encrypt, 110 : cipher); 111 : 112 3 : if (dialect < SMB3_DIALECT_REVISION_300) { 113 0 : DBG_DEBUG("Invalid SMB3 dialect!\n"); 114 0 : return false; 115 : } 116 : 117 3 : if (encrypt != DCERPC_SMB_ENCRYPTION_REQUIRED) { 118 0 : DBG_DEBUG("Invalid SMB3 encryption!\n"); 119 0 : return false; 120 : } 121 : 122 3 : switch (cipher) { 123 3 : case SMB2_ENCRYPTION_AES128_CCM: 124 : case SMB2_ENCRYPTION_AES128_GCM: 125 3 : break; 126 0 : default: 127 0 : DBG_DEBUG("Invalid SMB3 cipher!\n"); 128 0 : return false; 129 : } 130 : 131 3 : return true; 132 : }