1/* 2 Unix SMB/Netbios implementation. 3 Version 3.0 4 handle NLTMSSP, client server side parsing 5 6 Copyright (C) Andrew Tridgell 2001 7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2001-2005 8 Copyright (C) Stefan Metzmacher 2005 9 10 This program is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation; either version 3 of the License, or 13 (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program. If not, see <http://www.gnu.org/licenses/>. 22*/ 23 24#include "includes.h" 25#include "auth/ntlmssp/ntlmssp.h" 26#include "../librpc/gen_ndr/ntlmssp.h" 27#include "../libcli/auth/libcli_auth.h" 28#include "librpc/gen_ndr/ndr_dcerpc.h" 29#include "auth/credentials/credentials.h" 30#include "auth/gensec/gensec.h" 31#include "auth/gensec/gensec_proto.h" 32#include "param/param.h" 33 34/** 35 * Callbacks for NTLMSSP - for both client and server operating modes 36 * 37 */ 38 39static const struct ntlmssp_callbacks { 40 enum ntlmssp_role role; 41 enum ntlmssp_message_type command; 42 NTSTATUS (*sync_fn)(struct gensec_security *gensec_security, 43 TALLOC_CTX *out_mem_ctx, 44 DATA_BLOB in, DATA_BLOB *out); 45} ntlmssp_callbacks[] = { 46 { 47 .role = NTLMSSP_CLIENT, 48 .command = NTLMSSP_INITIAL, 49 .sync_fn = ntlmssp_client_initial, 50 },{ 51 .role = NTLMSSP_SERVER, 52 .command = NTLMSSP_NEGOTIATE, 53 .sync_fn = ntlmssp_server_negotiate, 54 },{ 55 .role = NTLMSSP_CLIENT, 56 .command = NTLMSSP_CHALLENGE, 57 .sync_fn = ntlmssp_client_challenge, 58 },{ 59 .role = NTLMSSP_SERVER, 60 .command = NTLMSSP_AUTH, 61 .sync_fn = ntlmssp_server_auth, 62 } 63}; 64 65 66/** 67 * Print out the NTLMSSP flags for debugging 68 * @param neg_flags The flags from the packet 69 */ 70 71void debug_ntlmssp_flags(uint32_t neg_flags) 72{ 73 DEBUG(3,("Got NTLMSSP neg_flags=0x%08x\n", neg_flags)); 74 75 if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) 76 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_UNICODE\n")); 77 if (neg_flags & NTLMSSP_NEGOTIATE_OEM) 78 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_OEM\n")); 79 if (neg_flags & NTLMSSP_REQUEST_TARGET) 80 DEBUGADD(4, (" NTLMSSP_REQUEST_TARGET\n")); 81 if (neg_flags & NTLMSSP_NEGOTIATE_SIGN) 82 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_SIGN\n")); 83 if (neg_flags & NTLMSSP_NEGOTIATE_SEAL) 84 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_SEAL\n")); 85 if (neg_flags & NTLMSSP_NEGOTIATE_DATAGRAM) 86 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_DATAGRAM\n")); 87 if (neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) 88 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_LM_KEY\n")); 89 if (neg_flags & NTLMSSP_NEGOTIATE_NETWARE) 90 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NETWARE\n")); 91 if (neg_flags & NTLMSSP_NEGOTIATE_NTLM) 92 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NTLM\n")); 93 if (neg_flags & NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED) 94 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED\n")); 95 if (neg_flags & NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED) 96 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED\n")); 97 if (neg_flags & NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL) 98 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL\n")); 99 if (neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) 100 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n")); 101 if (neg_flags & NTLMSSP_REQUEST_NON_NT_SESSION_KEY) 102 DEBUGADD(4, (" NTLMSSP_REQUEST_NON_NT_SESSION_KEY\n")); 103 if (neg_flags & NTLMSSP_NEGOTIATE_NTLM2) 104 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_NTLM2\n")); 105 if (neg_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) 106 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_TARGET_INFO\n")); 107 if (neg_flags & NTLMSSP_NEGOTIATE_128) 108 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_128\n")); 109 if (neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) 110 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_KEY_EXCH\n")); 111 if (neg_flags & NTLMSSP_NEGOTIATE_56) 112 DEBUGADD(4, (" NTLMSSP_NEGOTIATE_56\n")); 113} 114 115static NTSTATUS gensec_ntlmssp_magic(struct gensec_security *gensec_security, 116 const DATA_BLOB *first_packet) 117{ 118 if (first_packet->length > 8 && memcmp("NTLMSSP\0", first_packet->data, 8) == 0) { 119 return NT_STATUS_OK; 120 } else { 121 return NT_STATUS_INVALID_PARAMETER; 122 } 123} 124 125static NTSTATUS gensec_ntlmssp_update_find(struct gensec_ntlmssp_state *gensec_ntlmssp_state, 126 const DATA_BLOB input, uint32_t *idx) 127{ 128 struct gensec_security *gensec_security = gensec_ntlmssp_state->gensec_security; 129 uint32_t ntlmssp_command; 130 uint32_t i; 131 132 if (gensec_ntlmssp_state->expected_state == NTLMSSP_DONE) { 133 /* We are strict here because other modules, which we 134 * don't fully control (such as GSSAPI) are also 135 * strict, but are tested less often */ 136 137 DEBUG(1, ("Called NTLMSSP after state machine was 'done'\n")); 138 return NT_STATUS_INVALID_PARAMETER; 139 } 140 141 if (!input.length) { 142 switch (gensec_ntlmssp_state->role) { 143 case NTLMSSP_CLIENT: 144 ntlmssp_command = NTLMSSP_INITIAL; 145 break; 146 case NTLMSSP_SERVER: 147 if (gensec_security->want_features & GENSEC_FEATURE_DATAGRAM_MODE) { 148 /* 'datagram' mode - no neg packet */ 149 ntlmssp_command = NTLMSSP_NEGOTIATE; 150 } else { 151 /* This is normal in SPNEGO mech negotiation fallback */ 152 DEBUG(2, ("Failed to parse NTLMSSP packet: zero length\n")); 153 return NT_STATUS_INVALID_PARAMETER; 154 } 155 break; 156 } 157 } else { 158 if (!msrpc_parse(gensec_ntlmssp_state, 159 &input, "Cd", 160 "NTLMSSP", 161 &ntlmssp_command)) { 162 DEBUG(1, ("Failed to parse NTLMSSP packet, could not extract NTLMSSP command\n")); 163 dump_data(2, input.data, input.length); 164 return NT_STATUS_INVALID_PARAMETER; 165 } 166 } 167 168 if (ntlmssp_command != gensec_ntlmssp_state->expected_state) { 169 DEBUG(2, ("got NTLMSSP command %u, expected %u\n", ntlmssp_command, gensec_ntlmssp_state->expected_state)); 170 return NT_STATUS_INVALID_PARAMETER; 171 } 172 173 for (i=0; i < ARRAY_SIZE(ntlmssp_callbacks); i++) { 174 if (ntlmssp_callbacks[i].role == gensec_ntlmssp_state->role && 175 ntlmssp_callbacks[i].command == ntlmssp_command) { 176 *idx = i; 177 return NT_STATUS_OK; 178 } 179 } 180 181 DEBUG(1, ("failed to find NTLMSSP callback for NTLMSSP mode %u, command %u\n", 182 gensec_ntlmssp_state->role, ntlmssp_command)); 183 184 return NT_STATUS_INVALID_PARAMETER; 185} 186 187/** 188 * Next state function for the wrapped NTLMSSP state machine 189 * 190 * @param gensec_security GENSEC state, initialised to NTLMSSP 191 * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on 192 * @param in The request, as a DATA_BLOB 193 * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx 194 * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent, 195 * or NT_STATUS_OK if the user is authenticated. 196 */ 197 198static NTSTATUS gensec_ntlmssp_update(struct gensec_security *gensec_security, 199 TALLOC_CTX *out_mem_ctx, 200 const DATA_BLOB input, DATA_BLOB *out) 201{ 202 struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data; 203 NTSTATUS status; 204 uint32_t i; 205 206 *out = data_blob(NULL, 0); 207 208 if (!out_mem_ctx) { 209 /* if the caller doesn't want to manage/own the memory, 210 we can put it on our context */ 211 out_mem_ctx = gensec_ntlmssp_state; 212 } 213 214 status = gensec_ntlmssp_update_find(gensec_ntlmssp_state, input, &i); 215 NT_STATUS_NOT_OK_RETURN(status); 216 217 status = ntlmssp_callbacks[i].sync_fn(gensec_security, out_mem_ctx, input, out); 218 NT_STATUS_NOT_OK_RETURN(status); 219 220 return NT_STATUS_OK; 221} 222 223/** 224 * Return the NTLMSSP master session key 225 * 226 * @param gensec_ntlmssp_state NTLMSSP State 227 */ 228 229NTSTATUS gensec_ntlmssp_session_key(struct gensec_security *gensec_security, 230 DATA_BLOB *session_key) 231{ 232 struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data; 233 234 if (gensec_ntlmssp_state->expected_state != NTLMSSP_DONE) { 235 return NT_STATUS_NO_USER_SESSION_KEY; 236 } 237 238 if (!gensec_ntlmssp_state->session_key.data) { 239 return NT_STATUS_NO_USER_SESSION_KEY; 240 } 241 *session_key = gensec_ntlmssp_state->session_key; 242 243 return NT_STATUS_OK; 244} 245 246void ntlmssp_handle_neg_flags(struct gensec_ntlmssp_state *gensec_ntlmssp_state, 247 uint32_t neg_flags, bool allow_lm) 248{ 249 if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) { 250 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE; 251 gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_OEM; 252 gensec_ntlmssp_state->unicode = true; 253 } else { 254 gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_UNICODE; 255 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM; 256 gensec_ntlmssp_state->unicode = false; 257 } 258 259 if ((neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) && allow_lm && !gensec_ntlmssp_state->use_ntlmv2) { 260 /* other end forcing us to use LM */ 261 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY; 262 gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; 263 } else { 264 gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY; 265 } 266 267 if (!(neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)) { 268 gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_ALWAYS_SIGN; 269 } 270 271 if (!(neg_flags & NTLMSSP_NEGOTIATE_SIGN)) { 272 gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN; 273 } 274 275 if (!(neg_flags & NTLMSSP_NEGOTIATE_SEAL)) { 276 gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SEAL; 277 } 278 279 if (!(neg_flags & NTLMSSP_NEGOTIATE_NTLM2)) { 280 gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; 281 } 282 283 if (!(neg_flags & NTLMSSP_NEGOTIATE_128)) { 284 gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_128; 285 } 286 287 if (!(neg_flags & NTLMSSP_NEGOTIATE_56)) { 288 gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_56; 289 } 290 291 if (!(neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) { 292 gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_KEY_EXCH; 293 } 294 295 /* Woop Woop - unknown flag for Windows compatibility... 296 What does this really do ? JRA. */ 297 if (!(neg_flags & NTLMSSP_NEGOTIATE_VERSION)) { 298 gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_VERSION; 299 } 300 301 if ((neg_flags & NTLMSSP_REQUEST_TARGET)) { 302 gensec_ntlmssp_state->neg_flags |= NTLMSSP_REQUEST_TARGET; 303 } 304 305} 306 307/** 308 Weaken NTLMSSP keys to cope with down-level clients and servers. 309 310 We probably should have some parameters to control this, but as 311 it only occours for LM_KEY connections, and this is controlled 312 by the client lanman auth/lanman auth parameters, it isn't too bad. 313*/ 314 315DATA_BLOB ntlmssp_weakend_key(struct gensec_ntlmssp_state *gensec_ntlmssp_state, 316 TALLOC_CTX *mem_ctx) 317{ 318 DATA_BLOB weakened_key = data_blob_talloc(mem_ctx, 319 gensec_ntlmssp_state->session_key.data, 320 gensec_ntlmssp_state->session_key.length); 321 /* Nothing to weaken. We certainly don't want to 'extend' the length... */ 322 if (weakened_key.length < 16) { 323 /* perhaps there was no key? */ 324 return weakened_key; 325 } 326 327 /* Key weakening not performed on the master key for NTLM2 328 and does not occour for NTLM1. Therefore we only need 329 to do this for the LM_KEY. 330 */ 331 if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) { 332 /* LM key doesn't support 128 bit crypto, so this is 333 * the best we can do. If you negotiate 128 bit, but 334 * not 56, you end up with 40 bit... */ 335 if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) { 336 weakened_key.data[7] = 0xa0; 337 weakened_key.length = 8; 338 } else { /* forty bits */ 339 weakened_key.data[5] = 0xe5; 340 weakened_key.data[6] = 0x38; 341 weakened_key.data[7] = 0xb0; 342 weakened_key.length = 8; 343 } 344 } 345 return weakened_key; 346} 347 348static bool gensec_ntlmssp_have_feature(struct gensec_security *gensec_security, 349 uint32_t feature) 350{ 351 struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data; 352 if (feature & GENSEC_FEATURE_SIGN) { 353 if (!gensec_ntlmssp_state->session_key.length) { 354 return false; 355 } 356 if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) { 357 return true; 358 } 359 } 360 if (feature & GENSEC_FEATURE_SEAL) { 361 if (!gensec_ntlmssp_state->session_key.length) { 362 return false; 363 } 364 if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) { 365 return true; 366 } 367 } 368 if (feature & GENSEC_FEATURE_SESSION_KEY) { 369 if (gensec_ntlmssp_state->session_key.length) { 370 return true; 371 } 372 } 373 if (feature & GENSEC_FEATURE_DCE_STYLE) { 374 return true; 375 } 376 if (feature & GENSEC_FEATURE_ASYNC_REPLIES) { 377 if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { 378 return true; 379 } 380 } 381 return false; 382} 383 384NTSTATUS gensec_ntlmssp_start(struct gensec_security *gensec_security) 385{ 386 struct gensec_ntlmssp_state *gensec_ntlmssp_state; 387 388 gensec_ntlmssp_state = talloc_zero(gensec_security, struct gensec_ntlmssp_state); 389 if (!gensec_ntlmssp_state) { 390 return NT_STATUS_NO_MEMORY; 391 } 392 393 gensec_ntlmssp_state->gensec_security = gensec_security; 394 gensec_ntlmssp_state->auth_context = NULL; 395 gensec_ntlmssp_state->server_info = NULL; 396 397 gensec_security->private_data = gensec_ntlmssp_state; 398 return NT_STATUS_OK; 399} 400 401static const char *gensec_ntlmssp_oids[] = { 402 GENSEC_OID_NTLMSSP, 403 NULL 404}; 405 406static const struct gensec_security_ops gensec_ntlmssp_security_ops = { 407 .name = "ntlmssp", 408 .sasl_name = "NTLM", 409 .auth_type = DCERPC_AUTH_TYPE_NTLMSSP, 410 .oid = gensec_ntlmssp_oids, 411 .client_start = gensec_ntlmssp_client_start, 412 .server_start = gensec_ntlmssp_server_start, 413 .magic = gensec_ntlmssp_magic, 414 .update = gensec_ntlmssp_update, 415 .sig_size = gensec_ntlmssp_sig_size, 416 .sign_packet = gensec_ntlmssp_sign_packet, 417 .check_packet = gensec_ntlmssp_check_packet, 418 .seal_packet = gensec_ntlmssp_seal_packet, 419 .unseal_packet = gensec_ntlmssp_unseal_packet, 420 .wrap = gensec_ntlmssp_wrap, 421 .unwrap = gensec_ntlmssp_unwrap, 422 .session_key = gensec_ntlmssp_session_key, 423 .session_info = gensec_ntlmssp_session_info, 424 .have_feature = gensec_ntlmssp_have_feature, 425 .enabled = true, 426 .priority = GENSEC_NTLMSSP 427}; 428 429 430_PUBLIC_ NTSTATUS gensec_ntlmssp_init(void) 431{ 432 NTSTATUS ret; 433 434 ret = gensec_register(&gensec_ntlmssp_security_ops); 435 if (!NT_STATUS_IS_OK(ret)) { 436 DEBUG(0,("Failed to register '%s' gensec backend!\n", 437 gensec_ntlmssp_security_ops.name)); 438 return ret; 439 } 440 441 return ret; 442} 443