1/* 2 Unix SMB/CIFS implementation. 3 SMB Signing Code 4 Copyright (C) Jeremy Allison 2003. 5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003 6 Copyright (C) Stefan Metzmacher 2009 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22#include "includes.h" 23 24/* Used by the SMB signing functions. */ 25 26struct smb_signing_state { 27 /* is signing localy allowed */ 28 bool allowed; 29 30 /* is signing localy mandatory */ 31 bool mandatory; 32 33 /* is signing negotiated by the peer */ 34 bool negotiated; 35 36 /* send BSRSPYL signatures */ 37 bool bsrspyl; 38 39 bool active; /* Have I ever seen a validly signed packet? */ 40 41 /* mac_key.length > 0 means signing is started */ 42 DATA_BLOB mac_key; 43 44 /* the next expected seqnum */ 45 uint32_t seqnum; 46}; 47 48static void smb_signing_reset_info(struct smb_signing_state *si) 49{ 50 si->active = false; 51 si->bsrspyl = false; 52 data_blob_free(&si->mac_key); 53 si->seqnum = 0; 54} 55 56struct smb_signing_state *smb_signing_init(TALLOC_CTX *mem_ctx, 57 bool allowed, 58 bool mandatory) 59{ 60 struct smb_signing_state *si; 61 62 si = talloc_zero(mem_ctx, struct smb_signing_state); 63 if (si == NULL) { 64 return NULL; 65 } 66 67 if (mandatory) { 68 allowed = true; 69 } 70 71 si->allowed = allowed; 72 si->mandatory = mandatory; 73 74 return si; 75} 76 77static bool smb_signing_good(struct smb_signing_state *si, 78 bool good, uint32_t seq) 79{ 80 if (good) { 81 if (!si->active) { 82 si->active = true; 83 } 84 return true; 85 } 86 87 if (!si->mandatory && !si->active) { 88 /* Non-mandatory signing - just turn off if this is the first bad packet.. */ 89 DEBUG(5, ("smb_signing_good: signing negotiated but not required and peer\n" 90 "isn't sending correct signatures. Turning off.\n")); 91 smb_signing_reset_info(si); 92 return true; 93 } 94 95 /* Mandatory signing or bad packet after signing started - fail and disconnect. */ 96 DEBUG(0, ("smb_signing_good: BAD SIG: seq %u\n", (unsigned int)seq)); 97 return false; 98} 99 100static void smb_signing_md5(const DATA_BLOB *mac_key, 101 const uint8_t *buf, uint32_t seq_number, 102 uint8_t calc_md5_mac[16]) 103{ 104 const size_t offset_end_of_sig = (smb_ss_field + 8); 105 uint8_t sequence_buf[8]; 106 struct MD5Context md5_ctx; 107 108 /* 109 * Firstly put the sequence number into the first 4 bytes. 110 * and zero out the next 4 bytes. 111 * 112 * We do this here, to avoid modifying the packet. 113 */ 114 115 DEBUG(10,("smb_signing_md5: sequence number %u\n", seq_number )); 116 117 SIVAL(sequence_buf, 0, seq_number); 118 SIVAL(sequence_buf, 4, 0); 119 120 /* Calculate the 16 byte MAC - but don't alter the data in the 121 incoming packet. 122 123 This makes for a bit of fussing about, but it's not too bad. 124 */ 125 MD5Init(&md5_ctx); 126 127 /* intialise with the key */ 128 MD5Update(&md5_ctx, mac_key->data, mac_key->length); 129 130 /* copy in the first bit of the SMB header */ 131 MD5Update(&md5_ctx, buf + 4, smb_ss_field - 4); 132 133 /* copy in the sequence number, instead of the signature */ 134 MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf)); 135 136 /* copy in the rest of the packet in, skipping the signature */ 137 MD5Update(&md5_ctx, buf + offset_end_of_sig, 138 smb_len(buf) - (offset_end_of_sig - 4)); 139 140 /* calculate the MD5 sig */ 141 MD5Final(calc_md5_mac, &md5_ctx); 142} 143 144uint32_t smb_signing_next_seqnum(struct smb_signing_state *si, bool oneway) 145{ 146 uint32_t seqnum; 147 148 if (si->mac_key.length == 0) { 149 return 0; 150 } 151 152 seqnum = si->seqnum; 153 if (oneway) { 154 si->seqnum += 1; 155 } else { 156 si->seqnum += 2; 157 } 158 159 return seqnum; 160} 161 162void smb_signing_cancel_reply(struct smb_signing_state *si, bool oneway) 163{ 164 if (si->mac_key.length == 0) { 165 return; 166 } 167 168 if (oneway) { 169 si->seqnum -= 1; 170 } else { 171 si->seqnum -= 2; 172 } 173} 174 175void smb_signing_sign_pdu(struct smb_signing_state *si, 176 uint8_t *outbuf, uint32_t seqnum) 177{ 178 uint8_t calc_md5_mac[16]; 179 uint16_t flags2; 180 181 if (si->mac_key.length == 0) { 182 if (!si->bsrspyl) { 183 return; 184 } 185 } 186 187 /* JRA Paranioa test - we should be able to get rid of this... */ 188 if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) { 189 DEBUG(1,("smb_signing_sign_pdu: Logic error. " 190 "Can't check signature on short packet! smb_len = %u\n", 191 smb_len(outbuf))); 192 abort(); 193 } 194 195 /* mark the packet as signed - BEFORE we sign it...*/ 196 flags2 = SVAL(outbuf,smb_flg2); 197 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES; 198 SSVAL(outbuf, smb_flg2, flags2); 199 200 if (si->bsrspyl) { 201 /* I wonder what BSRSPYL stands for - but this is what MS 202 actually sends! */ 203 memcpy(calc_md5_mac, "BSRSPYL ", 8); 204 } else { 205 smb_signing_md5(&si->mac_key, outbuf, 206 seqnum, calc_md5_mac); 207 } 208 209 DEBUG(10, ("smb_signing_sign_pdu: sent SMB signature of\n")); 210 dump_data(10, calc_md5_mac, 8); 211 212 memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8); 213 214/* outbuf[smb_ss_field+2]=0; 215 Uncomment this to test if the remote server actually verifies signatures...*/ 216} 217 218bool smb_signing_check_pdu(struct smb_signing_state *si, 219 const uint8_t *inbuf, uint32_t seqnum) 220{ 221 bool good; 222 uint8_t calc_md5_mac[16]; 223 const uint8_t *reply_sent_mac; 224 225 if (si->mac_key.length == 0) { 226 return true; 227 } 228 229 if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) { 230 DEBUG(1,("smb_signing_check_pdu: Can't check signature " 231 "on short packet! smb_len = %u\n", 232 smb_len(inbuf))); 233 return False; 234 } 235 236 smb_signing_md5(&si->mac_key, inbuf, 237 seqnum, calc_md5_mac); 238 239 reply_sent_mac = &inbuf[smb_ss_field]; 240 good = (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0); 241 242 if (!good) { 243 int i; 244 const int sign_range = 5; 245 246 DEBUG(5, ("smb_signing_check_pdu: BAD SIG: wanted SMB signature of\n")); 247 dump_data(5, calc_md5_mac, 8); 248 249 DEBUG(5, ("smb_signing_check_pdu: BAD SIG: got SMB signature of\n")); 250 dump_data(5, reply_sent_mac, 8); 251 252 for (i = -sign_range; i < sign_range; i++) { 253 smb_signing_md5(&si->mac_key, inbuf, 254 seqnum+i, calc_md5_mac); 255 if (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0) { 256 DEBUG(0,("smb_signing_check_pdu: " 257 "out of seq. seq num %u matches. " 258 "We were expecting seq %u\n", 259 (unsigned int)seqnum+i, 260 (unsigned int)seqnum)); 261 break; 262 } 263 } 264 } else { 265 DEBUG(10, ("smb_signing_check_pdu: seq %u: " 266 "got good SMB signature of\n", 267 (unsigned int)seqnum)); 268 dump_data(10, reply_sent_mac, 8); 269 } 270 271 return smb_signing_good(si, good, seqnum); 272} 273 274bool smb_signing_set_bsrspyl(struct smb_signing_state *si) 275{ 276 if (!si->negotiated) { 277 return false; 278 } 279 280 if (si->active) { 281 return false; 282 } 283 284 si->bsrspyl = true; 285 286 return true; 287} 288 289bool smb_signing_activate(struct smb_signing_state *si, 290 const DATA_BLOB user_session_key, 291 const DATA_BLOB response) 292{ 293 size_t len; 294 off_t ofs; 295 296 if (!user_session_key.length) { 297 return false; 298 } 299 300 if (!si->negotiated) { 301 return false; 302 } 303 304 if (si->active) { 305 return false; 306 } 307 308 if (si->mac_key.length > 0) { 309 return false; 310 } 311 312 smb_signing_reset_info(si); 313 314 len = response.length + user_session_key.length; 315 si->mac_key = data_blob_talloc(si, NULL, len); 316 317 ofs = 0; 318 memcpy(&si->mac_key.data[ofs], user_session_key.data, user_session_key.length); 319 320 DEBUG(10, ("smb_signing_activate: user_session_key\n")); 321 dump_data(10, user_session_key.data, user_session_key.length); 322 323 if (response.length) { 324 ofs = user_session_key.length; 325 memcpy(&si->mac_key.data[ofs], response.data, response.length); 326 DEBUG(10, ("smb_signing_activate: response_data\n")); 327 dump_data(10, response.data, response.length); 328 } else { 329 DEBUG(10, ("smb_signing_activate: NULL response_data\n")); 330 } 331 332 dump_data_pw("smb_signing_activate: mac key is:\n", 333 si->mac_key.data, si->mac_key.length); 334 335 /* Initialise the sequence number */ 336 si->seqnum = 2; 337 338 return true; 339} 340 341bool smb_signing_is_active(struct smb_signing_state *si) 342{ 343 return si->active; 344} 345 346bool smb_signing_is_allowed(struct smb_signing_state *si) 347{ 348 return si->allowed; 349} 350 351bool smb_signing_is_mandatory(struct smb_signing_state *si) 352{ 353 return si->mandatory; 354} 355 356bool smb_signing_set_negotiated(struct smb_signing_state *si) 357{ 358 if (!si->allowed) { 359 return false; 360 } 361 362 si->negotiated = true; 363 364 return true; 365} 366 367bool smb_signing_is_negotiated(struct smb_signing_state *si) 368{ 369 return si->negotiated; 370} 371