Changeset 745 for trunk/server/source4/auth/ntlmssp
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 1 deleted
- 6 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source4/auth/ntlmssp/ntlmssp.c
r414 r745 24 24 #include "includes.h" 25 25 #include "auth/ntlmssp/ntlmssp.h" 26 #include "../librpc/gen_ndr/ntlmssp.h"27 26 #include "../libcli/auth/libcli_auth.h" 28 27 #include "librpc/gen_ndr/ndr_dcerpc.h" 29 #include "auth/credentials/credentials.h"30 28 #include "auth/gensec/gensec.h" 31 29 #include "auth/gensec/gensec_proto.h" 32 #include "param/param.h"33 30 34 31 /** … … 51 48 .role = NTLMSSP_SERVER, 52 49 .command = NTLMSSP_NEGOTIATE, 53 .sync_fn = ntlmssp_server_negotiate,50 .sync_fn = gensec_ntlmssp_server_negotiate, 54 51 },{ 55 52 .role = NTLMSSP_CLIENT, … … 59 56 .role = NTLMSSP_SERVER, 60 57 .command = NTLMSSP_AUTH, 61 .sync_fn = ntlmssp_server_auth,58 .sync_fn = gensec_ntlmssp_server_auth, 62 59 } 63 60 }; 64 61 65 66 /**67 * Print out the NTLMSSP flags for debugging68 * @param neg_flags The flags from the packet69 */70 71 void 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 62 115 63 static NTSTATUS gensec_ntlmssp_magic(struct gensec_security *gensec_security, … … 123 71 } 124 72 125 static NTSTATUS gensec_ntlmssp_update_find(struct gensec_ntlmssp_state *gensec_ntlmssp_state,73 static NTSTATUS gensec_ntlmssp_update_find(struct ntlmssp_state *ntlmssp_state, 126 74 const DATA_BLOB input, uint32_t *idx) 127 75 { 128 struct gensec_security *gensec_security = gensec_ntlmssp_state->gensec_security; 76 struct gensec_ntlmssp_context *gensec_ntlmssp = 77 talloc_get_type_abort(ntlmssp_state->callback_private, 78 struct gensec_ntlmssp_context); 79 struct gensec_security *gensec_security = gensec_ntlmssp->gensec_security; 129 80 uint32_t ntlmssp_command; 130 81 uint32_t i; 131 82 132 if ( gensec_ntlmssp_state->expected_state == NTLMSSP_DONE) {83 if (ntlmssp_state->expected_state == NTLMSSP_DONE) { 133 84 /* We are strict here because other modules, which we 134 85 * don't fully control (such as GSSAPI) are also … … 140 91 141 92 if (!input.length) { 142 switch ( gensec_ntlmssp_state->role) {93 switch (ntlmssp_state->role) { 143 94 case NTLMSSP_CLIENT: 144 95 ntlmssp_command = NTLMSSP_INITIAL; … … 156 107 } 157 108 } else { 158 if (!msrpc_parse( gensec_ntlmssp_state,109 if (!msrpc_parse(ntlmssp_state, 159 110 &input, "Cd", 160 111 "NTLMSSP", … … 166 117 } 167 118 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));119 if (ntlmssp_command != ntlmssp_state->expected_state) { 120 DEBUG(2, ("got NTLMSSP command %u, expected %u\n", ntlmssp_command, ntlmssp_state->expected_state)); 170 121 return NT_STATUS_INVALID_PARAMETER; 171 122 } 172 123 173 124 for (i=0; i < ARRAY_SIZE(ntlmssp_callbacks); i++) { 174 if (ntlmssp_callbacks[i].role == gensec_ntlmssp_state->role &&125 if (ntlmssp_callbacks[i].role == ntlmssp_state->role && 175 126 ntlmssp_callbacks[i].command == ntlmssp_command) { 176 127 *idx = i; … … 180 131 181 132 DEBUG(1, ("failed to find NTLMSSP callback for NTLMSSP mode %u, command %u\n", 182 gensec_ntlmssp_state->role, ntlmssp_command));133 ntlmssp_state->role, ntlmssp_command)); 183 134 184 135 return NT_STATUS_INVALID_PARAMETER; … … 200 151 const DATA_BLOB input, DATA_BLOB *out) 201 152 { 202 struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data; 153 struct gensec_ntlmssp_context *gensec_ntlmssp = 154 talloc_get_type_abort(gensec_security->private_data, 155 struct gensec_ntlmssp_context); 156 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state; 203 157 NTSTATUS status; 204 158 uint32_t i; … … 209 163 /* if the caller doesn't want to manage/own the memory, 210 164 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);165 out_mem_ctx = ntlmssp_state; 166 } 167 168 status = gensec_ntlmssp_update_find(ntlmssp_state, input, &i); 215 169 NT_STATUS_NOT_OK_RETURN(status); 216 170 … … 224 178 * Return the NTLMSSP master session key 225 179 * 226 * @param gensec_ntlmssp_state NTLMSSP State180 * @param ntlmssp_state NTLMSSP State 227 181 */ 228 182 … … 230 184 DATA_BLOB *session_key) 231 185 { 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) { 186 struct gensec_ntlmssp_context *gensec_ntlmssp = 187 talloc_get_type_abort(gensec_security->private_data, 188 struct gensec_ntlmssp_context); 189 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state; 190 191 if (ntlmssp_state->expected_state != NTLMSSP_DONE) { 235 192 return NT_STATUS_NO_USER_SESSION_KEY; 236 193 } 237 194 238 if (! gensec_ntlmssp_state->session_key.data) {195 if (!ntlmssp_state->session_key.data) { 239 196 return NT_STATUS_NO_USER_SESSION_KEY; 240 197 } 241 *session_key = gensec_ntlmssp_state->session_key;198 *session_key = ntlmssp_state->session_key; 242 199 243 200 return NT_STATUS_OK; 244 }245 246 void 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 as311 it only occours for LM_KEY connections, and this is controlled312 by the client lanman auth/lanman auth parameters, it isn't too bad.313 */314 315 DATA_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 NTLM2328 and does not occour for NTLM1. Therefore we only need329 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 is333 * the best we can do. If you negotiate 128 bit, but334 * 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 201 } 347 202 … … 349 204 uint32_t feature) 350 205 { 351 struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data; 206 struct gensec_ntlmssp_context *gensec_ntlmssp = 207 talloc_get_type_abort(gensec_security->private_data, 208 struct gensec_ntlmssp_context); 209 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state; 210 352 211 if (feature & GENSEC_FEATURE_SIGN) { 353 if (! gensec_ntlmssp_state->session_key.length) {212 if (!ntlmssp_state->session_key.length) { 354 213 return false; 355 214 } 356 if ( gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) {215 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) { 357 216 return true; 358 217 } 359 218 } 360 219 if (feature & GENSEC_FEATURE_SEAL) { 361 if (! gensec_ntlmssp_state->session_key.length) {220 if (!ntlmssp_state->session_key.length) { 362 221 return false; 363 222 } 364 if ( gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {223 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) { 365 224 return true; 366 225 } 367 226 } 368 227 if (feature & GENSEC_FEATURE_SESSION_KEY) { 369 if ( gensec_ntlmssp_state->session_key.length) {228 if (ntlmssp_state->session_key.length) { 370 229 return true; 371 230 } … … 375 234 } 376 235 if (feature & GENSEC_FEATURE_ASYNC_REPLIES) { 377 if ( gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {236 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { 378 237 return true; 379 238 } … … 384 243 NTSTATUS gensec_ntlmssp_start(struct gensec_security *gensec_security) 385 244 { 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) { 245 struct gensec_ntlmssp_context *gensec_ntlmssp; 246 struct ntlmssp_state *ntlmssp_state; 247 248 gensec_ntlmssp = talloc_zero(gensec_security, 249 struct gensec_ntlmssp_context); 250 if (!gensec_ntlmssp) { 390 251 return NT_STATUS_NO_MEMORY; 391 252 } 392 253 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; 254 gensec_ntlmssp->gensec_security = gensec_security; 255 256 ntlmssp_state = talloc_zero(gensec_ntlmssp, 257 struct ntlmssp_state); 258 if (!ntlmssp_state) { 259 return NT_STATUS_NO_MEMORY; 260 } 261 262 ntlmssp_state->callback_private = gensec_ntlmssp; 263 264 gensec_ntlmssp->ntlmssp_state = ntlmssp_state; 265 266 gensec_security->private_data = gensec_ntlmssp; 398 267 return NT_STATUS_OK; 399 268 } … … 406 275 static const struct gensec_security_ops gensec_ntlmssp_security_ops = { 407 276 .name = "ntlmssp", 408 .sasl_name = "NTLM",277 .sasl_name = GENSEC_SASL_NAME_NTLMSSP, /* "NTLM" */ 409 278 .auth_type = DCERPC_AUTH_TYPE_NTLMSSP, 410 279 .oid = gensec_ntlmssp_oids, -
trunk/server/source4/auth/ntlmssp/ntlmssp.h
r414 r745 1 /* 1 /* 2 2 Unix SMB/CIFS implementation. 3 3 SMB parameters and setup … … 5 5 Copyright (C) Luke Kenneth Casson Leighton 1996-1997 6 6 Copyright (C) Paul Ashton 1997 7 7 Copyright (C) Andrew Bartlett 2010 8 8 9 This program is free software; you can redistribute it and/or modify 9 10 it under the terms of the GNU General Public License as published by 10 11 the Free Software Foundation; either version 3 of the License, or 11 12 (at your option) any later version. 12 13 13 14 This program is distributed in the hope that it will be useful, 14 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 17 GNU General Public License for more details. 17 18 18 19 You should have received a copy of the GNU General Public License 19 20 along with this program. If not, see <http://www.gnu.org/licenses/>. 20 21 */ 21 22 22 #include "librpc/gen_ndr/samr.h"23 23 #include "../librpc/gen_ndr/ntlmssp.h" 24 #include "../libcli/auth/ntlmssp.h" 24 25 25 /* NTLMSSP mode */ 26 enum ntlmssp_role 27 { 28 NTLMSSP_SERVER, 29 NTLMSSP_CLIENT 30 }; 31 32 /* NTLMSSP message types */ 33 enum ntlmssp_message_type 34 { 35 NTLMSSP_INITIAL = 0 /* samba internal state */, 36 NTLMSSP_NEGOTIATE = 1, 37 NTLMSSP_CHALLENGE = 2, 38 NTLMSSP_AUTH = 3, 39 NTLMSSP_UNKNOWN = 4, 40 NTLMSSP_DONE = 5 /* samba final state */ 41 }; 42 43 struct gensec_ntlmssp_state 44 { 26 struct gensec_ntlmssp_context { 45 27 struct gensec_security *gensec_security; 46 47 enum ntlmssp_role role; 48 enum samr_Role server_role; 49 uint32_t expected_state; 50 51 bool unicode; 52 bool use_ntlmv2; 53 bool use_nt_response; /* Set to 'False' to debug what happens when the NT response is omited */ 54 bool allow_lm_key; /* The LM_KEY code is not functional at this point, and it's not 55 very secure anyway */ 56 57 bool server_multiple_authentications; /* Set to 'True' to allow squid 2.5 58 style 'challenge caching' */ 59 60 char *user; 61 const char *domain; 62 const char *workstation; 63 char *server_domain; 64 65 DATA_BLOB internal_chal; /* Random challenge as supplied to the client for NTLM authentication */ 66 67 DATA_BLOB chal; /* Random challenge as input into the actual NTLM (or NTLM2) authentication */ 68 DATA_BLOB lm_resp; 69 DATA_BLOB nt_resp; 70 DATA_BLOB session_key; 71 72 uint32_t neg_flags; /* the current state of negotiation with the NTLMSSP partner */ 73 74 /* internal variables used by KEY_EXCH (client-supplied user session key */ 75 DATA_BLOB encrypted_session_key; 76 77 /** 78 * Callback to get the 'challenge' used for NTLM authentication. 79 * 80 * @param ntlmssp_state This structure 81 * @return 8 bytes of challenge data, determined by the server to be the challenge for NTLM authentication 82 * 83 */ 84 const uint8_t *(*get_challenge)(const struct gensec_ntlmssp_state *); 85 86 /** 87 * Callback to find if the challenge used by NTLM authentication may be modified 88 * 89 * The NTLM2 authentication scheme modifies the effective challenge, but this is not compatiable with the 90 * current 'security=server' implementation.. 91 * 92 * @param ntlmssp_state This structure 93 * @return Can the challenge be set to arbitary values? 94 * 95 */ 96 bool (*may_set_challenge)(const struct gensec_ntlmssp_state *); 97 98 /** 99 * Callback to set the 'challenge' used for NTLM authentication. 100 * 101 * The callback may use the void *auth_context to store state information, but the same value is always available 102 * from the DATA_BLOB chal on this structure. 103 * 104 * @param ntlmssp_state This structure 105 * @param challenge 8 bytes of data, agreed by the client and server to be the effective challenge for NTLM2 authentication 106 * 107 */ 108 NTSTATUS (*set_challenge)(struct gensec_ntlmssp_state *, DATA_BLOB *challenge); 109 110 /** 111 * Callback to check the user's password. 112 * 113 * The callback must reads the feilds of this structure for the information it needs on the user 114 * @param ntlmssp_state This structure 115 * @param nt_session_key If an NT session key is returned by the authentication process, return it here 116 * @param lm_session_key If an LM session key is returned by the authentication process, return it here 117 * 118 */ 119 NTSTATUS (*check_password)(struct gensec_ntlmssp_state *, 120 TALLOC_CTX *mem_ctx, 121 DATA_BLOB *nt_session_key, DATA_BLOB *lm_session_key); 122 123 const char *server_name; 124 125 bool doing_ntlm2; 126 127 union { 128 /* NTLM */ 129 struct { 130 uint32_t seq_num; 131 struct arcfour_state *arcfour_state; 132 } ntlm; 133 134 /* NTLM2 */ 135 struct { 136 uint32_t send_seq_num; 137 uint32_t recv_seq_num; 138 DATA_BLOB send_sign_key; 139 DATA_BLOB recv_sign_key; 140 struct arcfour_state *send_seal_arcfour_state; 141 struct arcfour_state *recv_seal_arcfour_state; 142 143 /* internal variables used by NTLM2 */ 144 uint8_t session_nonce[16]; 145 } ntlm2; 146 } crypt; 147 28 struct ntlmssp_state *ntlmssp_state; 148 29 struct auth_context *auth_context; 149 struct auth_ serversupplied_info *server_info;30 struct auth_user_info_dc *user_info_dc; 150 31 }; 151 32 … … 153 34 struct auth_session_info; 154 35 36 NTSTATUS gensec_ntlmssp_init(void); 37 155 38 #include "auth/ntlmssp/proto.h" -
trunk/server/source4/auth/ntlmssp/ntlmssp_client.c
r414 r745 24 24 #include "includes.h" 25 25 #include "auth/ntlmssp/ntlmssp.h" 26 #include "../librpc/gen_ndr/ntlmssp.h"27 26 #include "../lib/crypto/crypto.h" 28 27 #include "../libcli/auth/libcli_auth.h" … … 30 29 #include "auth/gensec/gensec.h" 31 30 #include "param/param.h" 31 #include "libcli/auth/ntlmssp_private.h" 32 32 33 33 /********************************************************************* … … 49 49 DATA_BLOB in, DATA_BLOB *out) 50 50 { 51 struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data; 52 const char *domain = gensec_ntlmssp_state->domain; 51 struct gensec_ntlmssp_context *gensec_ntlmssp = 52 talloc_get_type_abort(gensec_security->private_data, 53 struct gensec_ntlmssp_context); 54 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state; 55 const char *domain = ntlmssp_state->domain; 53 56 const char *workstation = cli_credentials_get_workstation(gensec_security->credentials); 57 NTSTATUS status; 54 58 55 59 /* These don't really matter in the initial packet, so don't panic if they are not set */ … … 62 66 } 63 67 64 if ( gensec_ntlmssp_state->unicode) {65 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE;68 if (ntlmssp_state->unicode) { 69 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE; 66 70 } else { 67 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM;71 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM; 68 72 } 69 73 70 if ( gensec_ntlmssp_state->use_ntlmv2) {71 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;74 if (ntlmssp_state->use_ntlmv2) { 75 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2; 72 76 } 73 77 74 78 /* generate the ntlmssp negotiate packet */ 75 msrpc_gen(out_mem_ctx,79 status = msrpc_gen(out_mem_ctx, 76 80 out, "CddAA", 77 81 "NTLMSSP", 78 82 NTLMSSP_NEGOTIATE, 79 gensec_ntlmssp_state->neg_flags,83 ntlmssp_state->neg_flags, 80 84 domain, 81 85 workstation); 82 86 83 gensec_ntlmssp_state->expected_state = NTLMSSP_CHALLENGE; 87 if (!NT_STATUS_IS_OK(status)) { 88 return status; 89 } 90 91 ntlmssp_state->expected_state = NTLMSSP_CHALLENGE; 84 92 85 93 return NT_STATUS_MORE_PROCESSING_REQUIRED; … … 100 108 const DATA_BLOB in, DATA_BLOB *out) 101 109 { 102 struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data; 110 struct gensec_ntlmssp_context *gensec_ntlmssp = 111 talloc_get_type_abort(gensec_security->private_data, 112 struct gensec_ntlmssp_context); 113 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state; 103 114 uint32_t chal_flags, ntlmssp_command, unkn1, unkn2; 104 115 DATA_BLOB server_domain_blob; … … 140 151 debug_ntlmssp_flags(chal_flags); 141 152 142 ntlmssp_handle_neg_flags( gensec_ntlmssp_state, chal_flags, gensec_ntlmssp_state->allow_lm_key);143 144 if ( gensec_ntlmssp_state->unicode) {153 ntlmssp_handle_neg_flags(ntlmssp_state, chal_flags, ntlmssp_state->allow_lm_key); 154 155 if (ntlmssp_state->unicode) { 145 156 if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) { 146 157 chal_parse_string = "CdUdbddB"; … … 174 185 } 175 186 176 gensec_ntlmssp_state->server_domain = server_domain; 187 if (chal_flags & NTLMSSP_TARGET_TYPE_SERVER) { 188 ntlmssp_state->server.is_standalone = true; 189 } else { 190 ntlmssp_state->server.is_standalone = false; 191 } 192 /* TODO: parse struct_blob and fill in the rest */ 193 ntlmssp_state->server.netbios_name = ""; 194 ntlmssp_state->server.netbios_domain = server_domain; 195 ntlmssp_state->server.dns_name = ""; 196 ntlmssp_state->server.dns_domain = ""; 177 197 178 198 if (challenge_blob.length != 8) { … … 184 204 &user, &domain); 185 205 186 if ( gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {206 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { 187 207 flags |= CLI_CRED_NTLM2; 188 208 } 189 if ( gensec_ntlmssp_state->use_ntlmv2) {209 if (ntlmssp_state->use_ntlmv2) { 190 210 flags |= CLI_CRED_NTLMv2_AUTH; 191 211 } 192 if ( gensec_ntlmssp_state->use_nt_response) {212 if (ntlmssp_state->use_nt_response) { 193 213 flags |= CLI_CRED_NTLM_AUTH; 194 214 } 195 if (lp _client_lanman_auth(gensec_security->settings->lp_ctx)) {215 if (lpcfg_client_lanman_auth(gensec_security->settings->lp_ctx)) { 196 216 flags |= CLI_CRED_LANMAN_AUTH; 197 217 } … … 209 229 /* LM Key is still possible, just silly. Fortunetly 210 230 * we require command line options to end up here */ 211 /* gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY; */231 /* ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY; */ 212 232 } 213 233 214 234 if (!(flags & CLI_CRED_NTLM2)) { 215 235 /* NTLM2 is incompatible... */ 216 gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;236 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; 217 237 } 218 238 219 if (( gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)220 && lp _client_lanman_auth(gensec_security->settings->lp_ctx) && lm_session_key.length == 16) {239 if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) 240 && lpcfg_client_lanman_auth(gensec_security->settings->lp_ctx) && lm_session_key.length == 16) { 221 241 DATA_BLOB new_session_key = data_blob_talloc(mem_ctx, NULL, 16); 222 242 if (lm_response.length == 24) { … … 235 255 /* Key exchange encryptes a new client-generated session key with 236 256 the password-derived key */ 237 if ( gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {257 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { 238 258 /* Make up a new session key */ 239 259 uint8_t client_session_key[16]; … … 241 261 242 262 /* Encrypt the new session key with the old one */ 243 encrypted_session_key = data_blob_talloc( gensec_ntlmssp_state,263 encrypted_session_key = data_blob_talloc(ntlmssp_state, 244 264 client_session_key, sizeof(client_session_key)); 245 265 dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length); … … 252 272 253 273 DEBUG(3, ("NTLMSSP: Set final flags:\n")); 254 debug_ntlmssp_flags( gensec_ntlmssp_state->neg_flags);274 debug_ntlmssp_flags(ntlmssp_state->neg_flags); 255 275 256 276 /* this generates the actual auth packet */ 257 if (!msrpc_gen(mem_ctx,277 nt_status = msrpc_gen(mem_ctx, 258 278 out, auth_gen_string, 259 279 "NTLMSSP", … … 265 285 cli_credentials_get_workstation(gensec_security->credentials), 266 286 encrypted_session_key.data, encrypted_session_key.length, 267 gensec_ntlmssp_state->neg_flags)) { 287 ntlmssp_state->neg_flags); 288 if (!NT_STATUS_IS_OK(nt_status)) { 268 289 talloc_free(mem_ctx); 269 return NT_STATUS_NO_MEMORY;270 } 271 272 gensec_ntlmssp_state->session_key = session_key;273 talloc_steal( gensec_ntlmssp_state, session_key.data);290 return nt_status; 291 } 292 293 ntlmssp_state->session_key = session_key; 294 talloc_steal(ntlmssp_state, session_key.data); 274 295 275 296 talloc_steal(out_mem_ctx, out->data); 276 297 277 gensec_ntlmssp_state->chal = challenge_blob;278 gensec_ntlmssp_state->lm_resp = lm_response;279 talloc_steal( gensec_ntlmssp_state->lm_resp.data, lm_response.data);280 gensec_ntlmssp_state->nt_resp = nt_response;281 talloc_steal( gensec_ntlmssp_state->nt_resp.data, nt_response.data);282 283 gensec_ntlmssp_state->expected_state = NTLMSSP_DONE;298 ntlmssp_state->chal = challenge_blob; 299 ntlmssp_state->lm_resp = lm_response; 300 talloc_steal(ntlmssp_state->lm_resp.data, lm_response.data); 301 ntlmssp_state->nt_resp = nt_response; 302 talloc_steal(ntlmssp_state->nt_resp.data, nt_response.data); 303 304 ntlmssp_state->expected_state = NTLMSSP_DONE; 284 305 285 306 if (gensec_security->want_features & (GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL)) { 286 nt_status = ntlmssp_sign_init( gensec_ntlmssp_state);307 nt_status = ntlmssp_sign_init(ntlmssp_state); 287 308 if (!NT_STATUS_IS_OK(nt_status)) { 288 309 DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n", … … 299 320 NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_security) 300 321 { 301 struct gensec_ntlmssp_state *gensec_ntlmssp_state; 322 struct gensec_ntlmssp_context *gensec_ntlmssp; 323 struct ntlmssp_state *ntlmssp_state; 302 324 NTSTATUS nt_status; 303 325 … … 305 327 NT_STATUS_NOT_OK_RETURN(nt_status); 306 328 307 gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data; 308 309 gensec_ntlmssp_state->role = NTLMSSP_CLIENT; 310 311 gensec_ntlmssp_state->domain = lp_workgroup(gensec_security->settings->lp_ctx); 312 313 gensec_ntlmssp_state->unicode = gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "unicode", true); 314 315 gensec_ntlmssp_state->use_nt_response = gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "send_nt_reponse", true); 316 317 gensec_ntlmssp_state->allow_lm_key = (lp_client_lanman_auth(gensec_security->settings->lp_ctx) 329 gensec_ntlmssp = talloc_get_type_abort(gensec_security->private_data, 330 struct gensec_ntlmssp_context); 331 ntlmssp_state = gensec_ntlmssp->ntlmssp_state; 332 333 ntlmssp_state->role = NTLMSSP_CLIENT; 334 335 ntlmssp_state->domain = lpcfg_workgroup(gensec_security->settings->lp_ctx); 336 337 ntlmssp_state->unicode = gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "unicode", true); 338 339 ntlmssp_state->use_nt_response = gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "send_nt_reponse", true); 340 341 ntlmssp_state->allow_lm_key = (lpcfg_client_lanman_auth(gensec_security->settings->lp_ctx) 318 342 && (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "allow_lm_key", false) 319 343 || gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "lm_key", false))); 320 344 321 gensec_ntlmssp_state->use_ntlmv2 = lp_client_ntlmv2_auth(gensec_security->settings->lp_ctx);322 323 gensec_ntlmssp_state->expected_state = NTLMSSP_INITIAL;324 325 gensec_ntlmssp_state->neg_flags =345 ntlmssp_state->use_ntlmv2 = lpcfg_client_ntlmv2_auth(gensec_security->settings->lp_ctx); 346 347 ntlmssp_state->expected_state = NTLMSSP_INITIAL; 348 349 ntlmssp_state->neg_flags = 326 350 NTLMSSP_NEGOTIATE_NTLM | 327 351 NTLMSSP_REQUEST_TARGET; 328 352 329 353 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "128bit", true)) { 330 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_128;354 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_128; 331 355 } 332 356 333 357 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "56bit", false)) { 334 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56;358 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56; 335 359 } 336 360 337 361 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "lm_key", false)) { 338 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY;362 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY; 339 363 } 340 364 341 365 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "keyexchange", true)) { 342 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_KEY_EXCH;366 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_KEY_EXCH; 343 367 } 344 368 345 369 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "alwayssign", true)) { 346 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;370 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; 347 371 } 348 372 349 373 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_client", "ntlm2", true)) { 350 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;374 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2; 351 375 } else { 352 376 /* apparently we can't do ntlmv2 if we don't do ntlm2 */ 353 gensec_ntlmssp_state->use_ntlmv2 = false;377 ntlmssp_state->use_ntlmv2 = false; 354 378 } 355 379 … … 364 388 * sealing. (It is actually pulled out and used directly) 365 389 */ 366 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;390 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; 367 391 } 368 392 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) { 369 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;393 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; 370 394 } 371 395 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) { 372 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; 373 } 374 375 gensec_security->private_data = gensec_ntlmssp_state; 396 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; 397 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; 398 } 376 399 377 400 return NT_STATUS_OK; -
trunk/server/source4/auth/ntlmssp/ntlmssp_server.c
r414 r745 24 24 #include "includes.h" 25 25 #include "system/network.h" 26 #include "lib/tsocket/tsocket.h" 26 27 #include "auth/ntlmssp/ntlmssp.h" 27 #include "../librpc/gen_ndr/ntlmssp.h" 28 #include "../librpc/gen_ndr/ndr_ntlmssp.h" 29 #include "../libcli/auth/ntlmssp_ndr.h" 30 #include "../libcli/auth/ntlmssp_private.h" 28 31 #include "../libcli/auth/libcli_auth.h" 29 32 #include "../lib/crypto/crypto.h" 30 33 #include "auth/gensec/gensec.h" 34 #include "auth/gensec/gensec_proto.h" 31 35 #include "auth/auth.h" 32 #include "auth/ntlm/auth_proto.h"33 36 #include "param/param.h" 34 #include "auth/session_proto.h" 35 36 /** 37 * Set a username on an NTLMSSP context - ensures it is talloc()ed 38 * 39 */ 40 41 static NTSTATUS ntlmssp_set_username(struct gensec_ntlmssp_state *gensec_ntlmssp_state, const char *user) 42 { 43 if (!user) { 44 /* it should be at least "" */ 45 DEBUG(1, ("NTLMSSP failed to set username - cannot accept NULL username\n")); 46 return NT_STATUS_INVALID_PARAMETER; 47 } 48 gensec_ntlmssp_state->user = talloc_strdup(gensec_ntlmssp_state, user); 49 if (!gensec_ntlmssp_state->user) { 50 return NT_STATUS_NO_MEMORY; 51 } 52 return NT_STATUS_OK; 53 } 54 55 /** 56 * Set a domain on an NTLMSSP context - ensures it is talloc()ed 57 * 58 */ 59 static NTSTATUS ntlmssp_set_domain(struct gensec_ntlmssp_state *gensec_ntlmssp_state, const char *domain) 60 { 61 gensec_ntlmssp_state->domain = talloc_strdup(gensec_ntlmssp_state, domain); 62 if (!gensec_ntlmssp_state->domain) { 63 return NT_STATUS_NO_MEMORY; 64 } 65 return NT_STATUS_OK; 66 } 67 68 /** 69 * Set a workstation on an NTLMSSP context - ensures it is talloc()ed 70 * 71 */ 72 static NTSTATUS ntlmssp_set_workstation(struct gensec_ntlmssp_state *gensec_ntlmssp_state, const char *workstation) 73 { 74 gensec_ntlmssp_state->workstation = talloc_strdup(gensec_ntlmssp_state, workstation); 75 if (!gensec_ntlmssp_state->workstation) { 76 return NT_STATUS_NO_MEMORY; 77 } 78 return NT_STATUS_OK; 79 } 80 81 /** 82 * Determine correct target name flags for reply, given server role 83 * and negotiated flags 84 * 85 * @param gensec_ntlmssp_state NTLMSSP State 86 * @param neg_flags The flags from the packet 87 * @param chal_flags The flags to be set in the reply packet 88 * @return The 'target name' string. 89 */ 90 91 static const char *ntlmssp_target_name(struct gensec_ntlmssp_state *gensec_ntlmssp_state, 92 uint32_t neg_flags, uint32_t *chal_flags) 93 { 94 if (neg_flags & NTLMSSP_REQUEST_TARGET) { 95 *chal_flags |= NTLMSSP_NEGOTIATE_TARGET_INFO; 96 *chal_flags |= NTLMSSP_REQUEST_TARGET; 97 if (gensec_ntlmssp_state->server_role == ROLE_STANDALONE) { 98 *chal_flags |= NTLMSSP_TARGET_TYPE_SERVER; 99 return gensec_ntlmssp_state->server_name; 100 } else { 101 *chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN; 102 return gensec_ntlmssp_state->domain; 103 }; 104 } else { 105 return ""; 106 } 107 } 108 109 110 111 /** 112 * Next state function for the Negotiate packet 113 * 37 38 /** 39 * Next state function for the Negotiate packet (GENSEC wrapper) 40 * 114 41 * @param gensec_security GENSEC state 115 42 * @param out_mem_ctx Memory context for *out 116 43 * @param in The request, as a DATA_BLOB. reply.data must be NULL 117 44 * @param out The reply, as an allocated DATA_BLOB, caller to free. 118 * @return Errors or MORE_PROCESSING_REQUIRED if (normal) a reply is required. 119 */ 120 121 NTSTATUS ntlmssp_server_negotiate(struct gensec_security *gensec_security, 122 TALLOC_CTX *out_mem_ctx, 123 const DATA_BLOB in, DATA_BLOB *out) 124 { 125 struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data; 126 DATA_BLOB struct_blob; 127 uint32_t neg_flags = 0; 128 uint32_t ntlmssp_command, chal_flags; 129 const uint8_t *cryptkey; 130 const char *target_name; 131 132 /* parse the NTLMSSP packet */ 133 #if 0 134 file_save("ntlmssp_negotiate.dat", request.data, request.length); 135 #endif 136 137 if (in.length) { 138 if ((in.length < 16) || !msrpc_parse(out_mem_ctx, 139 &in, "Cdd", 140 "NTLMSSP", 141 &ntlmssp_command, 142 &neg_flags)) { 143 DEBUG(1, ("ntlmssp_server_negotiate: failed to parse " 144 "NTLMSSP Negotiate of length %u:\n", 145 (unsigned int)in.length )); 146 dump_data(2, in.data, in.length); 147 return NT_STATUS_INVALID_PARAMETER; 148 } 149 debug_ntlmssp_flags(neg_flags); 150 } 151 152 ntlmssp_handle_neg_flags(gensec_ntlmssp_state, neg_flags, gensec_ntlmssp_state->allow_lm_key); 153 154 /* Ask our caller what challenge they would like in the packet */ 155 cryptkey = gensec_ntlmssp_state->get_challenge(gensec_ntlmssp_state); 156 if (!cryptkey) { 157 DEBUG(1, ("ntlmssp_server_negotiate: backend doesn't give a challenge\n")); 158 return NT_STATUS_INTERNAL_ERROR; 159 } 160 161 /* Check if we may set the challenge */ 162 if (!gensec_ntlmssp_state->may_set_challenge(gensec_ntlmssp_state)) { 163 gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; 164 } 165 166 /* The flags we send back are not just the negotiated flags, 167 * they are also 'what is in this packet'. Therfore, we 168 * operate on 'chal_flags' from here on 169 */ 170 171 chal_flags = gensec_ntlmssp_state->neg_flags; 172 173 /* get the right name to fill in as 'target' */ 174 target_name = ntlmssp_target_name(gensec_ntlmssp_state, 175 neg_flags, &chal_flags); 176 if (target_name == NULL) 45 * @return Errors or MORE_PROCESSING_REQUIRED if (normal) a reply is required. 46 */ 47 48 NTSTATUS gensec_ntlmssp_server_negotiate(struct gensec_security *gensec_security, 49 TALLOC_CTX *out_mem_ctx, 50 const DATA_BLOB request, DATA_BLOB *reply) 51 { 52 struct gensec_ntlmssp_context *gensec_ntlmssp = 53 talloc_get_type_abort(gensec_security->private_data, 54 struct gensec_ntlmssp_context); 55 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state; 56 return ntlmssp_server_negotiate(ntlmssp_state, out_mem_ctx, request, reply); 57 } 58 59 /** 60 * Next state function for the Authenticate packet (GENSEC wrapper) 61 * 62 * @param gensec_security GENSEC state 63 * @param out_mem_ctx Memory context for *out 64 * @param in The request, as a DATA_BLOB. reply.data must be NULL 65 * @param out The reply, as an allocated DATA_BLOB, caller to free. 66 * @return Errors or NT_STATUS_OK if authentication sucessful 67 */ 68 69 NTSTATUS gensec_ntlmssp_server_auth(struct gensec_security *gensec_security, 70 TALLOC_CTX *out_mem_ctx, 71 const DATA_BLOB in, DATA_BLOB *out) 72 { 73 struct gensec_ntlmssp_context *gensec_ntlmssp = 74 talloc_get_type_abort(gensec_security->private_data, 75 struct gensec_ntlmssp_context); 76 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state; 77 return ntlmssp_server_auth(ntlmssp_state, out_mem_ctx, in, out); 78 } 79 80 /** 81 * Return the challenge as determined by the authentication subsystem 82 * @return an 8 byte random challenge 83 */ 84 85 static NTSTATUS auth_ntlmssp_get_challenge(const struct ntlmssp_state *ntlmssp_state, 86 uint8_t chal[8]) 87 { 88 struct gensec_ntlmssp_context *gensec_ntlmssp = 89 talloc_get_type_abort(ntlmssp_state->callback_private, 90 struct gensec_ntlmssp_context); 91 struct auth_context *auth_context = gensec_ntlmssp->auth_context; 92 NTSTATUS status; 93 94 status = auth_context->get_challenge(auth_context, chal); 95 if (!NT_STATUS_IS_OK(status)) { 96 DEBUG(1, ("auth_ntlmssp_get_challenge: failed to get challenge: %s\n", 97 nt_errstr(status))); 98 return status; 99 } 100 101 return NT_STATUS_OK; 102 } 103 104 /** 105 * Some authentication methods 'fix' the challenge, so we may not be able to set it 106 * 107 * @return If the effective challenge used by the auth subsystem may be modified 108 */ 109 static bool auth_ntlmssp_may_set_challenge(const struct ntlmssp_state *ntlmssp_state) 110 { 111 struct gensec_ntlmssp_context *gensec_ntlmssp = 112 talloc_get_type_abort(ntlmssp_state->callback_private, 113 struct gensec_ntlmssp_context); 114 struct auth_context *auth_context = gensec_ntlmssp->auth_context; 115 116 return auth_context->challenge_may_be_modified(auth_context); 117 } 118 119 /** 120 * NTLM2 authentication modifies the effective challenge, 121 * @param challenge The new challenge value 122 */ 123 static NTSTATUS auth_ntlmssp_set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge) 124 { 125 struct gensec_ntlmssp_context *gensec_ntlmssp = 126 talloc_get_type_abort(ntlmssp_state->callback_private, 127 struct gensec_ntlmssp_context); 128 struct auth_context *auth_context = gensec_ntlmssp->auth_context; 129 NTSTATUS nt_status; 130 const uint8_t *chal; 131 132 if (challenge->length != 8) { 177 133 return NT_STATUS_INVALID_PARAMETER; 178 179 gensec_ntlmssp_state->chal = data_blob_talloc(gensec_ntlmssp_state, cryptkey, 8); 180 gensec_ntlmssp_state->internal_chal = data_blob_talloc(gensec_ntlmssp_state, cryptkey, 8); 181 182 /* This creates the 'blob' of names that appears at the end of the packet */ 183 if (chal_flags & NTLMSSP_NEGOTIATE_TARGET_INFO) { 134 } 135 136 chal = challenge->data; 137 138 nt_status = auth_context->set_challenge(auth_context, 139 chal, 140 "NTLMSSP callback (NTLM2)"); 141 142 return nt_status; 143 } 144 145 /** 146 * Check the password on an NTLMSSP login. 147 * 148 * Return the session keys used on the connection. 149 */ 150 151 static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, 152 TALLOC_CTX *mem_ctx, 153 DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key) 154 { 155 struct gensec_ntlmssp_context *gensec_ntlmssp = 156 talloc_get_type_abort(ntlmssp_state->callback_private, 157 struct gensec_ntlmssp_context); 158 struct auth_context *auth_context = gensec_ntlmssp->auth_context; 159 NTSTATUS nt_status; 160 struct auth_usersupplied_info *user_info; 161 162 user_info = talloc_zero(ntlmssp_state, struct auth_usersupplied_info); 163 if (!user_info) { 164 return NT_STATUS_NO_MEMORY; 165 } 166 167 user_info->logon_parameters = MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT | MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT; 168 user_info->flags = 0; 169 user_info->mapped_state = false; 170 user_info->client.account_name = ntlmssp_state->user; 171 user_info->client.domain_name = ntlmssp_state->domain; 172 user_info->workstation_name = ntlmssp_state->client.netbios_name; 173 user_info->remote_host = gensec_get_remote_address(gensec_ntlmssp->gensec_security); 174 175 user_info->password_state = AUTH_PASSWORD_RESPONSE; 176 user_info->password.response.lanman = ntlmssp_state->lm_resp; 177 user_info->password.response.lanman.data = talloc_steal(user_info, ntlmssp_state->lm_resp.data); 178 user_info->password.response.nt = ntlmssp_state->nt_resp; 179 user_info->password.response.nt.data = talloc_steal(user_info, ntlmssp_state->nt_resp.data); 180 181 nt_status = auth_context->check_password(auth_context, 182 gensec_ntlmssp, 183 user_info, 184 &gensec_ntlmssp->user_info_dc); 185 talloc_free(user_info); 186 NT_STATUS_NOT_OK_RETURN(nt_status); 187 188 if (gensec_ntlmssp->user_info_dc->user_session_key.length) { 189 DEBUG(10, ("Got NT session key of length %u\n", 190 (unsigned)gensec_ntlmssp->user_info_dc->user_session_key.length)); 191 *user_session_key = gensec_ntlmssp->user_info_dc->user_session_key; 192 talloc_steal(mem_ctx, user_session_key->data); 193 gensec_ntlmssp->user_info_dc->user_session_key = data_blob_null; 194 } 195 if (gensec_ntlmssp->user_info_dc->lm_session_key.length) { 196 DEBUG(10, ("Got LM session key of length %u\n", 197 (unsigned)gensec_ntlmssp->user_info_dc->lm_session_key.length)); 198 *lm_session_key = gensec_ntlmssp->user_info_dc->lm_session_key; 199 talloc_steal(mem_ctx, lm_session_key->data); 200 gensec_ntlmssp->user_info_dc->lm_session_key = data_blob_null; 201 } 202 return nt_status; 203 } 204 205 /** 206 * Return the credentials of a logged on user, including session keys 207 * etc. 208 * 209 * Only valid after a successful authentication 210 * 211 * May only be called once per authentication. 212 * 213 */ 214 215 NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_security, 216 struct auth_session_info **session_info) 217 { 218 NTSTATUS nt_status; 219 struct gensec_ntlmssp_context *gensec_ntlmssp = 220 talloc_get_type_abort(gensec_security->private_data, 221 struct gensec_ntlmssp_context); 222 struct ntlmssp_state *ntlmssp_state = gensec_ntlmssp->ntlmssp_state; 223 224 nt_status = gensec_generate_session_info(ntlmssp_state, 225 gensec_security, 226 gensec_ntlmssp->user_info_dc, 227 session_info); 228 NT_STATUS_NOT_OK_RETURN(nt_status); 229 230 (*session_info)->session_key = data_blob_talloc(*session_info, 231 ntlmssp_state->session_key.data, 232 ntlmssp_state->session_key.length); 233 234 return NT_STATUS_OK; 235 } 236 237 /** 238 * Start NTLMSSP on the server side 239 * 240 */ 241 NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security) 242 { 243 NTSTATUS nt_status; 244 struct ntlmssp_state *ntlmssp_state; 245 struct gensec_ntlmssp_context *gensec_ntlmssp; 246 247 nt_status = gensec_ntlmssp_start(gensec_security); 248 NT_STATUS_NOT_OK_RETURN(nt_status); 249 250 gensec_ntlmssp = talloc_get_type_abort(gensec_security->private_data, 251 struct gensec_ntlmssp_context); 252 ntlmssp_state = gensec_ntlmssp->ntlmssp_state; 253 254 ntlmssp_state->role = NTLMSSP_SERVER; 255 256 ntlmssp_state->expected_state = NTLMSSP_NEGOTIATE; 257 258 ntlmssp_state->allow_lm_key = (lpcfg_lanman_auth(gensec_security->settings->lp_ctx) 259 && gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "allow_lm_key", false)); 260 261 ntlmssp_state->neg_flags = 262 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_VERSION; 263 264 ntlmssp_state->lm_resp = data_blob(NULL, 0); 265 ntlmssp_state->nt_resp = data_blob(NULL, 0); 266 267 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "128bit", true)) { 268 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_128; 269 } 270 271 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "56bit", true)) { 272 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56; 273 } 274 275 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "keyexchange", true)) { 276 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_KEY_EXCH; 277 } 278 279 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "alwayssign", true)) { 280 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; 281 } 282 283 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "ntlm2", true)) { 284 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2; 285 } 286 287 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) { 288 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; 289 } 290 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) { 291 ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; 292 } 293 294 gensec_ntlmssp->auth_context = gensec_security->auth_context; 295 296 ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge; 297 ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge; 298 ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge; 299 ntlmssp_state->check_password = auth_ntlmssp_check_password; 300 if (lpcfg_server_role(gensec_security->settings->lp_ctx) == ROLE_STANDALONE) { 301 ntlmssp_state->server.is_standalone = true; 302 } else { 303 ntlmssp_state->server.is_standalone = false; 304 } 305 306 ntlmssp_state->server.netbios_name = lpcfg_netbios_name(gensec_security->settings->lp_ctx); 307 308 ntlmssp_state->server.netbios_domain = lpcfg_workgroup(gensec_security->settings->lp_ctx); 309 310 { 184 311 char dnsdomname[MAXHOSTNAMELEN], dnsname[MAXHOSTNAMELEN]; 185 const char *target_name_dns = "";186 312 187 313 /* Find out the DNS domain name */ 188 314 dnsdomname[0] = '\0'; 189 safe_strcpy(dnsdomname, lp_realm(gensec_security->settings->lp_ctx), sizeof(dnsdomname) - 1); 190 strlower_m(dnsdomname); 315 safe_strcpy(dnsdomname, lpcfg_dnsdomain(gensec_security->settings->lp_ctx), sizeof(dnsdomname) - 1); 191 316 192 317 /* Find out the DNS host name */ 193 safe_strcpy(dnsname, gensec_ntlmssp_state->server_name, sizeof(dnsname) - 1);318 safe_strcpy(dnsname, ntlmssp_state->server.netbios_name, sizeof(dnsname) - 1); 194 319 if (dnsdomname[0] != '\0') { 195 320 safe_strcat(dnsname, ".", sizeof(dnsname) - 1); … … 198 323 strlower_m(dnsname); 199 324 200 if (chal_flags |= NTLMSSP_TARGET_TYPE_DOMAIN) { 201 target_name_dns = dnsdomname; 202 } else if (chal_flags |= NTLMSSP_TARGET_TYPE_SERVER) { 203 target_name_dns = dnsname; 204 } 205 206 msrpc_gen(out_mem_ctx, 207 &struct_blob, "aaaaa", 208 MsvAvNbDomainName, target_name, 209 MsvAvNbComputerName, gensec_ntlmssp_state->server_name, 210 MsvAvDnsDomainName, dnsdomname, 211 MsvAvDnsComputerName, dnsname, 212 MsvAvEOL, ""); 213 } else { 214 struct_blob = data_blob(NULL, 0); 215 } 216 217 { 218 /* Marshal the packet in the right format, be it unicode or ASCII */ 219 const char *gen_string; 220 if (gensec_ntlmssp_state->unicode) { 221 gen_string = "CdUdbddB"; 222 } else { 223 gen_string = "CdAdbddB"; 224 } 225 226 msrpc_gen(out_mem_ctx, 227 out, gen_string, 228 "NTLMSSP", 229 NTLMSSP_CHALLENGE, 230 target_name, 231 chal_flags, 232 cryptkey, 8, 233 0, 0, 234 struct_blob.data, struct_blob.length); 235 } 236 237 gensec_ntlmssp_state->expected_state = NTLMSSP_AUTH; 238 239 return NT_STATUS_MORE_PROCESSING_REQUIRED; 240 } 241 242 /** 243 * Next state function for the Authenticate packet 244 * 245 * @param gensec_ntlmssp_state NTLMSSP State 246 * @param request The request, as a DATA_BLOB 247 * @return Errors or NT_STATUS_OK. 248 */ 249 250 static NTSTATUS ntlmssp_server_preauth(struct gensec_ntlmssp_state *gensec_ntlmssp_state, 251 const DATA_BLOB request) 252 { 253 uint32_t ntlmssp_command, auth_flags; 254 NTSTATUS nt_status; 255 256 uint8_t session_nonce_hash[16]; 257 258 const char *parse_string; 259 char *domain = NULL; 260 char *user = NULL; 261 char *workstation = NULL; 262 263 #if 0 264 file_save("ntlmssp_auth.dat", request.data, request.length); 265 #endif 266 267 if (gensec_ntlmssp_state->unicode) { 268 parse_string = "CdBBUUUBd"; 269 } else { 270 parse_string = "CdBBAAABd"; 271 } 272 273 /* zero these out */ 274 data_blob_free(&gensec_ntlmssp_state->lm_resp); 275 data_blob_free(&gensec_ntlmssp_state->nt_resp); 276 data_blob_free(&gensec_ntlmssp_state->encrypted_session_key); 277 278 gensec_ntlmssp_state->user = NULL; 279 gensec_ntlmssp_state->domain = NULL; 280 gensec_ntlmssp_state->workstation = NULL; 281 282 /* now the NTLMSSP encoded auth hashes */ 283 if (!msrpc_parse(gensec_ntlmssp_state, 284 &request, parse_string, 285 "NTLMSSP", 286 &ntlmssp_command, 287 &gensec_ntlmssp_state->lm_resp, 288 &gensec_ntlmssp_state->nt_resp, 289 &domain, 290 &user, 291 &workstation, 292 &gensec_ntlmssp_state->encrypted_session_key, 293 &auth_flags)) { 294 DEBUG(10, ("ntlmssp_server_auth: failed to parse NTLMSSP (nonfatal):\n")); 295 dump_data(10, request.data, request.length); 296 297 /* zero this out */ 298 data_blob_free(&gensec_ntlmssp_state->encrypted_session_key); 299 auth_flags = 0; 300 301 /* Try again with a shorter string (Win9X truncates this packet) */ 302 if (gensec_ntlmssp_state->unicode) { 303 parse_string = "CdBBUUU"; 304 } else { 305 parse_string = "CdBBAAA"; 306 } 307 308 /* now the NTLMSSP encoded auth hashes */ 309 if (!msrpc_parse(gensec_ntlmssp_state, 310 &request, parse_string, 311 "NTLMSSP", 312 &ntlmssp_command, 313 &gensec_ntlmssp_state->lm_resp, 314 &gensec_ntlmssp_state->nt_resp, 315 &domain, 316 &user, 317 &workstation)) { 318 DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP:\n")); 319 dump_data(2, request.data, request.length); 320 321 return NT_STATUS_INVALID_PARAMETER; 322 } 323 } 324 325 if (auth_flags) 326 ntlmssp_handle_neg_flags(gensec_ntlmssp_state, auth_flags, gensec_ntlmssp_state->allow_lm_key); 327 328 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(gensec_ntlmssp_state, domain))) { 329 /* zero this out */ 330 data_blob_free(&gensec_ntlmssp_state->encrypted_session_key); 331 return nt_status; 332 } 333 334 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(gensec_ntlmssp_state, user))) { 335 /* zero this out */ 336 data_blob_free(&gensec_ntlmssp_state->encrypted_session_key); 337 return nt_status; 338 } 339 340 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_workstation(gensec_ntlmssp_state, workstation))) { 341 /* zero this out */ 342 data_blob_free(&gensec_ntlmssp_state->encrypted_session_key); 343 return nt_status; 344 } 345 346 DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n", 347 gensec_ntlmssp_state->user, gensec_ntlmssp_state->domain, gensec_ntlmssp_state->workstation, (unsigned long)gensec_ntlmssp_state->lm_resp.length, (unsigned long)gensec_ntlmssp_state->nt_resp.length)); 348 349 #if 0 350 file_save("nthash1.dat", &gensec_ntlmssp_state->nt_resp.data, &gensec_ntlmssp_state->nt_resp.length); 351 file_save("lmhash1.dat", &gensec_ntlmssp_state->lm_resp.data, &gensec_ntlmssp_state->lm_resp.length); 352 #endif 353 354 /* NTLM2 uses a 'challenge' that is made of up both the server challenge, and a 355 client challenge 356 357 However, the NTLM2 flag may still be set for the real NTLMv2 logins, be careful. 358 */ 359 if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { 360 if (gensec_ntlmssp_state->nt_resp.length == 24 && gensec_ntlmssp_state->lm_resp.length == 24) { 361 struct MD5Context md5_session_nonce_ctx; 362 SMB_ASSERT(gensec_ntlmssp_state->internal_chal.data 363 && gensec_ntlmssp_state->internal_chal.length == 8); 364 365 gensec_ntlmssp_state->doing_ntlm2 = true; 366 367 memcpy(gensec_ntlmssp_state->crypt.ntlm2.session_nonce, gensec_ntlmssp_state->internal_chal.data, 8); 368 memcpy(&gensec_ntlmssp_state->crypt.ntlm2.session_nonce[8], gensec_ntlmssp_state->lm_resp.data, 8); 369 370 MD5Init(&md5_session_nonce_ctx); 371 MD5Update(&md5_session_nonce_ctx, gensec_ntlmssp_state->crypt.ntlm2.session_nonce, 16); 372 MD5Final(session_nonce_hash, &md5_session_nonce_ctx); 373 374 gensec_ntlmssp_state->chal = data_blob_talloc(gensec_ntlmssp_state, 375 session_nonce_hash, 8); 376 377 /* LM response is no longer useful, zero it out */ 378 data_blob_free(&gensec_ntlmssp_state->lm_resp); 379 380 /* We changed the effective challenge - set it */ 381 if (!NT_STATUS_IS_OK(nt_status = 382 gensec_ntlmssp_state->set_challenge(gensec_ntlmssp_state, 383 &gensec_ntlmssp_state->chal))) { 384 /* zero this out */ 385 data_blob_free(&gensec_ntlmssp_state->encrypted_session_key); 386 return nt_status; 387 } 388 389 /* LM Key is incompatible... */ 390 gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY; 391 } 392 } 325 ntlmssp_state->server.dns_name = talloc_strdup(ntlmssp_state, 326 dnsname); 327 NT_STATUS_HAVE_NO_MEMORY(ntlmssp_state->server.dns_name); 328 329 ntlmssp_state->server.dns_domain = talloc_strdup(ntlmssp_state, 330 dnsdomname); 331 NT_STATUS_HAVE_NO_MEMORY(ntlmssp_state->server.dns_domain); 332 } 333 393 334 return NT_STATUS_OK; 394 335 } 395 336 396 /**397 * Next state function for the Authenticate packet398 * (after authentication - figures out the session keys etc)399 *400 * @param gensec_ntlmssp_state NTLMSSP State401 * @return Errors or NT_STATUS_OK.402 */403 404 static NTSTATUS ntlmssp_server_postauth(struct gensec_security *gensec_security,405 DATA_BLOB *user_session_key,406 DATA_BLOB *lm_session_key)407 {408 struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data;409 NTSTATUS nt_status;410 DATA_BLOB session_key = data_blob(NULL, 0);411 412 if (user_session_key)413 dump_data_pw("USER session key:\n", user_session_key->data, user_session_key->length);414 415 if (lm_session_key)416 dump_data_pw("LM first-8:\n", lm_session_key->data, lm_session_key->length);417 418 /* Handle the different session key derivation for NTLM2 */419 if (gensec_ntlmssp_state->doing_ntlm2) {420 if (user_session_key && user_session_key->data && user_session_key->length == 16) {421 session_key = data_blob_talloc(gensec_ntlmssp_state, NULL, 16);422 hmac_md5(user_session_key->data, gensec_ntlmssp_state->crypt.ntlm2.session_nonce,423 sizeof(gensec_ntlmssp_state->crypt.ntlm2.session_nonce), session_key.data);424 DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n"));425 dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);426 427 } else {428 DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n"));429 session_key = data_blob(NULL, 0);430 }431 } else if ((gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY)432 /* Ensure we can never get here on NTLMv2 */433 && (gensec_ntlmssp_state->nt_resp.length == 0 || gensec_ntlmssp_state->nt_resp.length == 24)) {434 435 if (lm_session_key && lm_session_key->data && lm_session_key->length >= 8) {436 if (gensec_ntlmssp_state->lm_resp.data && gensec_ntlmssp_state->lm_resp.length == 24) {437 session_key = data_blob_talloc(gensec_ntlmssp_state, NULL, 16);438 SMBsesskeygen_lm_sess_key(lm_session_key->data, gensec_ntlmssp_state->lm_resp.data,439 session_key.data);440 DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));441 dump_data_pw("LM session key:\n", session_key.data, session_key.length);442 } else {443 444 /* When there is no LM response, just use zeros */445 static const uint8_t zeros[24];446 session_key = data_blob_talloc(gensec_ntlmssp_state, NULL, 16);447 SMBsesskeygen_lm_sess_key(zeros, zeros,448 session_key.data);449 DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));450 dump_data_pw("LM session key:\n", session_key.data, session_key.length);451 }452 } else {453 /* LM Key not selected */454 gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;455 456 DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n"));457 session_key = data_blob(NULL, 0);458 }459 460 } else if (user_session_key && user_session_key->data) {461 session_key = data_blob_talloc(gensec_ntlmssp_state, user_session_key->data, user_session_key->length);462 DEBUG(10,("ntlmssp_server_auth: Using unmodified nt session key.\n"));463 dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);464 465 /* LM Key not selected */466 gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;467 468 } else if (lm_session_key && lm_session_key->data) {469 /* Very weird to have LM key, but no user session key, but anyway.. */470 session_key = data_blob_talloc(gensec_ntlmssp_state, lm_session_key->data, lm_session_key->length);471 DEBUG(10,("ntlmssp_server_auth: Using unmodified lm session key.\n"));472 dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);473 474 /* LM Key not selected */475 gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;476 477 } else {478 DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n"));479 session_key = data_blob(NULL, 0);480 481 /* LM Key not selected */482 gensec_ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;483 }484 485 /* With KEY_EXCH, the client supplies the proposed session key,486 but encrypts it with the long-term key */487 if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {488 if (!gensec_ntlmssp_state->encrypted_session_key.data489 || gensec_ntlmssp_state->encrypted_session_key.length != 16) {490 data_blob_free(&gensec_ntlmssp_state->encrypted_session_key);491 DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n",492 (unsigned)gensec_ntlmssp_state->encrypted_session_key.length));493 return NT_STATUS_INVALID_PARAMETER;494 } else if (!session_key.data || session_key.length != 16) {495 DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n",496 (unsigned)session_key.length));497 gensec_ntlmssp_state->session_key = session_key;498 } else {499 dump_data_pw("KEY_EXCH session key (enc):\n",500 gensec_ntlmssp_state->encrypted_session_key.data,501 gensec_ntlmssp_state->encrypted_session_key.length);502 arcfour_crypt(gensec_ntlmssp_state->encrypted_session_key.data,503 session_key.data,504 gensec_ntlmssp_state->encrypted_session_key.length);505 gensec_ntlmssp_state->session_key = data_blob_talloc(gensec_ntlmssp_state,506 gensec_ntlmssp_state->encrypted_session_key.data,507 gensec_ntlmssp_state->encrypted_session_key.length);508 dump_data_pw("KEY_EXCH session key:\n", gensec_ntlmssp_state->encrypted_session_key.data,509 gensec_ntlmssp_state->encrypted_session_key.length);510 talloc_free(session_key.data);511 }512 } else {513 gensec_ntlmssp_state->session_key = session_key;514 }515 516 if ((gensec_security->want_features & GENSEC_FEATURE_SIGN)517 || (gensec_security->want_features & GENSEC_FEATURE_SEAL)) {518 nt_status = ntlmssp_sign_init(gensec_ntlmssp_state);519 } else {520 nt_status = NT_STATUS_OK;521 }522 523 data_blob_free(&gensec_ntlmssp_state->encrypted_session_key);524 525 /* allow arbitarily many authentications, but watch that this will cause a526 memory leak, until the gensec_ntlmssp_state is shutdown527 */528 529 if (gensec_ntlmssp_state->server_multiple_authentications) {530 gensec_ntlmssp_state->expected_state = NTLMSSP_AUTH;531 } else {532 gensec_ntlmssp_state->expected_state = NTLMSSP_DONE;533 }534 535 return nt_status;536 }537 538 539 /**540 * Next state function for the Authenticate packet541 *542 * @param gensec_security GENSEC state543 * @param out_mem_ctx Memory context for *out544 * @param in The request, as a DATA_BLOB. reply.data must be NULL545 * @param out The reply, as an allocated DATA_BLOB, caller to free.546 * @return Errors or NT_STATUS_OK if authentication sucessful547 */548 549 NTSTATUS ntlmssp_server_auth(struct gensec_security *gensec_security,550 TALLOC_CTX *out_mem_ctx,551 const DATA_BLOB in, DATA_BLOB *out)552 {553 struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data;554 DATA_BLOB user_session_key = data_blob(NULL, 0);555 DATA_BLOB lm_session_key = data_blob(NULL, 0);556 NTSTATUS nt_status;557 558 TALLOC_CTX *mem_ctx = talloc_new(out_mem_ctx);559 if (!mem_ctx) {560 return NT_STATUS_NO_MEMORY;561 }562 563 /* zero the outbound NTLMSSP packet */564 *out = data_blob_talloc(out_mem_ctx, NULL, 0);565 566 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_server_preauth(gensec_ntlmssp_state, in))) {567 talloc_free(mem_ctx);568 return nt_status;569 }570 571 /*572 * Note we don't check here for NTLMv2 auth settings. If NTLMv2 auth573 * is required (by "ntlm auth = no" and "lm auth = no" being set in the574 * smb.conf file) and no NTLMv2 response was sent then the password check575 * will fail here. JRA.576 */577 578 /* Finally, actually ask if the password is OK */579 580 if (!NT_STATUS_IS_OK(nt_status = gensec_ntlmssp_state->check_password(gensec_ntlmssp_state, mem_ctx,581 &user_session_key, &lm_session_key))) {582 talloc_free(mem_ctx);583 return nt_status;584 }585 586 if (gensec_security->want_features587 & (GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL|GENSEC_FEATURE_SESSION_KEY)) {588 nt_status = ntlmssp_server_postauth(gensec_security, &user_session_key, &lm_session_key);589 talloc_free(mem_ctx);590 return nt_status;591 } else {592 gensec_ntlmssp_state->session_key = data_blob(NULL, 0);593 talloc_free(mem_ctx);594 return NT_STATUS_OK;595 }596 }597 598 /**599 * Return the challenge as determined by the authentication subsystem600 * @return an 8 byte random challenge601 */602 603 static const uint8_t *auth_ntlmssp_get_challenge(const struct gensec_ntlmssp_state *gensec_ntlmssp_state)604 {605 NTSTATUS status;606 const uint8_t *chal;607 608 status = gensec_ntlmssp_state->auth_context->get_challenge(gensec_ntlmssp_state->auth_context, &chal);609 if (!NT_STATUS_IS_OK(status)) {610 DEBUG(1, ("auth_ntlmssp_get_challenge: failed to get challenge: %s\n",611 nt_errstr(status)));612 return NULL;613 }614 615 return chal;616 }617 618 /**619 * Some authentication methods 'fix' the challenge, so we may not be able to set it620 *621 * @return If the effective challenge used by the auth subsystem may be modified622 */623 static bool auth_ntlmssp_may_set_challenge(const struct gensec_ntlmssp_state *gensec_ntlmssp_state)624 {625 return gensec_ntlmssp_state->auth_context->challenge_may_be_modified(gensec_ntlmssp_state->auth_context);626 }627 628 /**629 * NTLM2 authentication modifies the effective challenge,630 * @param challenge The new challenge value631 */632 static NTSTATUS auth_ntlmssp_set_challenge(struct gensec_ntlmssp_state *gensec_ntlmssp_state, DATA_BLOB *challenge)633 {634 NTSTATUS nt_status;635 struct auth_context *auth_context = gensec_ntlmssp_state->auth_context;636 const uint8_t *chal;637 638 if (challenge->length != 8) {639 return NT_STATUS_INVALID_PARAMETER;640 }641 642 chal = challenge->data;643 644 nt_status = gensec_ntlmssp_state->auth_context->set_challenge(auth_context,645 chal,646 "NTLMSSP callback (NTLM2)");647 648 return nt_status;649 }650 651 /**652 * Check the password on an NTLMSSP login.653 *654 * Return the session keys used on the connection.655 */656 657 static NTSTATUS auth_ntlmssp_check_password(struct gensec_ntlmssp_state *gensec_ntlmssp_state,658 TALLOC_CTX *mem_ctx,659 DATA_BLOB *user_session_key, DATA_BLOB *lm_session_key)660 {661 NTSTATUS nt_status;662 struct auth_usersupplied_info *user_info = talloc(mem_ctx, struct auth_usersupplied_info);663 if (!user_info) {664 return NT_STATUS_NO_MEMORY;665 }666 667 user_info->logon_parameters = MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT | MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;668 user_info->flags = 0;669 user_info->mapped_state = false;670 user_info->client.account_name = gensec_ntlmssp_state->user;671 user_info->client.domain_name = gensec_ntlmssp_state->domain;672 user_info->workstation_name = gensec_ntlmssp_state->workstation;673 user_info->remote_host = gensec_get_peer_addr(gensec_ntlmssp_state->gensec_security);674 675 user_info->password_state = AUTH_PASSWORD_RESPONSE;676 user_info->password.response.lanman = gensec_ntlmssp_state->lm_resp;677 user_info->password.response.lanman.data = talloc_steal(user_info, gensec_ntlmssp_state->lm_resp.data);678 user_info->password.response.nt = gensec_ntlmssp_state->nt_resp;679 user_info->password.response.nt.data = talloc_steal(user_info, gensec_ntlmssp_state->nt_resp.data);680 681 nt_status = gensec_ntlmssp_state->auth_context->check_password(gensec_ntlmssp_state->auth_context,682 mem_ctx,683 user_info,684 &gensec_ntlmssp_state->server_info);685 talloc_free(user_info);686 NT_STATUS_NOT_OK_RETURN(nt_status);687 688 talloc_steal(gensec_ntlmssp_state, gensec_ntlmssp_state->server_info);689 690 if (gensec_ntlmssp_state->server_info->user_session_key.length) {691 DEBUG(10, ("Got NT session key of length %u\n",692 (unsigned)gensec_ntlmssp_state->server_info->user_session_key.length));693 if (!talloc_reference(mem_ctx, gensec_ntlmssp_state->server_info->user_session_key.data)) {694 return NT_STATUS_NO_MEMORY;695 }696 697 *user_session_key = gensec_ntlmssp_state->server_info->user_session_key;698 }699 if (gensec_ntlmssp_state->server_info->lm_session_key.length) {700 DEBUG(10, ("Got LM session key of length %u\n",701 (unsigned)gensec_ntlmssp_state->server_info->lm_session_key.length));702 if (!talloc_reference(mem_ctx, gensec_ntlmssp_state->server_info->lm_session_key.data)) {703 return NT_STATUS_NO_MEMORY;704 }705 706 *lm_session_key = gensec_ntlmssp_state->server_info->lm_session_key;707 }708 return nt_status;709 }710 711 /**712 * Return the credentials of a logged on user, including session keys713 * etc.714 *715 * Only valid after a successful authentication716 *717 * May only be called once per authentication.718 *719 */720 721 NTSTATUS gensec_ntlmssp_session_info(struct gensec_security *gensec_security,722 struct auth_session_info **session_info)723 {724 NTSTATUS nt_status;725 struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data;726 727 nt_status = auth_generate_session_info(gensec_ntlmssp_state, gensec_security->event_ctx, gensec_security->settings->lp_ctx, gensec_ntlmssp_state->server_info, session_info);728 NT_STATUS_NOT_OK_RETURN(nt_status);729 730 (*session_info)->session_key = data_blob_talloc(*session_info,731 gensec_ntlmssp_state->session_key.data,732 gensec_ntlmssp_state->session_key.length);733 734 return NT_STATUS_OK;735 }736 737 /**738 * Start NTLMSSP on the server side739 *740 */741 NTSTATUS gensec_ntlmssp_server_start(struct gensec_security *gensec_security)742 {743 NTSTATUS nt_status;744 struct gensec_ntlmssp_state *gensec_ntlmssp_state;745 746 nt_status = gensec_ntlmssp_start(gensec_security);747 NT_STATUS_NOT_OK_RETURN(nt_status);748 749 gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data;750 751 gensec_ntlmssp_state->role = NTLMSSP_SERVER;752 753 gensec_ntlmssp_state->workstation = NULL;754 gensec_ntlmssp_state->server_name = lp_netbios_name(gensec_security->settings->lp_ctx);755 756 gensec_ntlmssp_state->domain = lp_workgroup(gensec_security->settings->lp_ctx);757 758 gensec_ntlmssp_state->expected_state = NTLMSSP_NEGOTIATE;759 760 gensec_ntlmssp_state->allow_lm_key = (lp_lanman_auth(gensec_security->settings->lp_ctx)761 && gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "allow_lm_key", false));762 763 gensec_ntlmssp_state->server_multiple_authentications = false;764 765 gensec_ntlmssp_state->neg_flags =766 NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_VERSION;767 768 gensec_ntlmssp_state->lm_resp = data_blob(NULL, 0);769 gensec_ntlmssp_state->nt_resp = data_blob(NULL, 0);770 gensec_ntlmssp_state->encrypted_session_key = data_blob(NULL, 0);771 772 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "128bit", true)) {773 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_128;774 }775 776 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "56bit", true)) {777 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56;778 }779 780 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "keyexchange", true)) {781 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_KEY_EXCH;782 }783 784 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "alwayssign", true)) {785 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;786 }787 788 if (gensec_setting_bool(gensec_security->settings, "ntlmssp_server", "ntlm2", true)) {789 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;790 }791 792 if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {793 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;794 }795 if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {796 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;797 }798 799 gensec_ntlmssp_state->auth_context = gensec_security->auth_context;800 801 gensec_ntlmssp_state->get_challenge = auth_ntlmssp_get_challenge;802 gensec_ntlmssp_state->may_set_challenge = auth_ntlmssp_may_set_challenge;803 gensec_ntlmssp_state->set_challenge = auth_ntlmssp_set_challenge;804 gensec_ntlmssp_state->check_password = auth_ntlmssp_check_password;805 gensec_ntlmssp_state->server_role = lp_server_role(gensec_security->settings->lp_ctx);806 807 return NT_STATUS_OK;808 }809 -
trunk/server/source4/auth/ntlmssp/ntlmssp_sign.c
r414 r745 1 /* 1 /* 2 2 * Unix SMB/CIFS implementation. 3 3 * Version 3.0 … … 5 5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2001 6 6 * Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003-2005 7 * 7 * 8 8 * This program is free software; you can redistribute it and/or modify 9 9 * it under the terms of the GNU General Public License as published by 10 10 * the Free Software Foundation; either version 3 of the License, or 11 11 * (at your option) any later version. 12 * 12 * 13 13 * This program is distributed in the hope that it will be useful, 14 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 16 * GNU General Public License for more details. 17 * 17 * 18 18 * You should have received a copy of the GNU General Public License 19 19 * along with this program; if not, see <http://www.gnu.org/licenses/>. … … 22 22 #include "includes.h" 23 23 #include "auth/ntlmssp/ntlmssp.h" 24 #include "../librpc/gen_ndr/ntlmssp.h"25 #include "../libcli/auth/libcli_auth.h"26 #include "../lib/crypto/crypto.h"27 24 #include "auth/gensec/gensec.h" 25 #include "../libcli/auth/ntlmssp_private.h" 28 26 29 #define CLI_SIGN "session key to client-to-server signing key magic constant" 30 #define CLI_SEAL "session key to client-to-server sealing key magic constant" 31 #define SRV_SIGN "session key to server-to-client signing key magic constant" 32 #define SRV_SEAL "session key to server-to-client sealing key magic constant" 33 34 /** 35 * Some notes on the NTLM2 code: 36 * 37 * NTLM2 is a AEAD system. This means that the data encrypted is not 38 * all the data that is signed. In DCE-RPC case, the headers of the 39 * DCE-RPC packets are also signed. This prevents some of the 40 * fun-and-games one might have by changing them. 41 * 42 */ 43 44 static void calc_ntlmv2_key(TALLOC_CTX *mem_ctx, 45 DATA_BLOB *subkey, 46 DATA_BLOB session_key, 47 const char *constant) 48 { 49 struct MD5Context ctx3; 50 *subkey = data_blob_talloc(mem_ctx, NULL, 16); 51 MD5Init(&ctx3); 52 MD5Update(&ctx3, session_key.data, session_key.length); 53 MD5Update(&ctx3, (const uint8_t *)constant, strlen(constant)+1); 54 MD5Final(subkey->data, &ctx3); 55 } 56 57 enum ntlmssp_direction { 58 NTLMSSP_SEND, 59 NTLMSSP_RECEIVE 60 }; 61 62 static NTSTATUS ntlmssp_make_packet_signature(struct gensec_ntlmssp_state *gensec_ntlmssp_state, 63 TALLOC_CTX *sig_mem_ctx, 64 const uint8_t *data, size_t length, 65 const uint8_t *whole_pdu, size_t pdu_length, 66 enum ntlmssp_direction direction, 67 DATA_BLOB *sig, bool encrypt_sig) 68 { 69 if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { 70 71 HMACMD5Context ctx; 72 uint8_t digest[16]; 73 uint8_t seq_num[4]; 74 75 *sig = data_blob_talloc(sig_mem_ctx, NULL, NTLMSSP_SIG_SIZE); 76 if (!sig->data) { 77 return NT_STATUS_NO_MEMORY; 78 } 79 80 switch (direction) { 81 case NTLMSSP_SEND: 82 SIVAL(seq_num, 0, gensec_ntlmssp_state->crypt.ntlm2.send_seq_num); 83 gensec_ntlmssp_state->crypt.ntlm2.send_seq_num++; 84 hmac_md5_init_limK_to_64(gensec_ntlmssp_state->crypt.ntlm2.send_sign_key.data, 85 gensec_ntlmssp_state->crypt.ntlm2.send_sign_key.length, &ctx); 86 break; 87 case NTLMSSP_RECEIVE: 88 SIVAL(seq_num, 0, gensec_ntlmssp_state->crypt.ntlm2.recv_seq_num); 89 gensec_ntlmssp_state->crypt.ntlm2.recv_seq_num++; 90 hmac_md5_init_limK_to_64(gensec_ntlmssp_state->crypt.ntlm2.recv_sign_key.data, 91 gensec_ntlmssp_state->crypt.ntlm2.recv_sign_key.length, &ctx); 92 break; 93 } 94 hmac_md5_update(seq_num, sizeof(seq_num), &ctx); 95 hmac_md5_update(whole_pdu, pdu_length, &ctx); 96 hmac_md5_final(digest, &ctx); 97 98 if (encrypt_sig && gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { 99 switch (direction) { 100 case NTLMSSP_SEND: 101 arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state, digest, 8); 102 break; 103 case NTLMSSP_RECEIVE: 104 arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm2.recv_seal_arcfour_state, digest, 8); 105 break; 106 } 107 } 108 109 SIVAL(sig->data, 0, NTLMSSP_SIGN_VERSION); 110 memcpy(sig->data + 4, digest, 8); 111 memcpy(sig->data + 12, seq_num, 4); 112 113 DEBUG(10, ("NTLM2: created signature over %llu bytes of input:\n", (unsigned long long)pdu_length)); 114 dump_data(11, sig->data, sig->length); 115 116 } else { 117 uint32_t crc; 118 crc = crc32_calc_buffer(data, length); 119 if (!msrpc_gen(sig_mem_ctx, 120 sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, gensec_ntlmssp_state->crypt.ntlm.seq_num)) { 121 return NT_STATUS_NO_MEMORY; 122 } 123 gensec_ntlmssp_state->crypt.ntlm.seq_num++; 124 125 arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm.arcfour_state, sig->data+4, sig->length-4); 126 127 DEBUG(10, ("NTLM1: created signature over %llu bytes of input:\n", (unsigned long long)length)); 128 dump_data(11, sig->data, sig->length); 129 } 130 return NT_STATUS_OK; 131 } 132 133 /* TODO: make this non-public */ 134 NTSTATUS gensec_ntlmssp_sign_packet(struct gensec_security *gensec_security, 135 TALLOC_CTX *sig_mem_ctx, 136 const uint8_t *data, size_t length, 137 const uint8_t *whole_pdu, size_t pdu_length, 27 NTSTATUS gensec_ntlmssp_sign_packet(struct gensec_security *gensec_security, 28 TALLOC_CTX *sig_mem_ctx, 29 const uint8_t *data, size_t length, 30 const uint8_t *whole_pdu, size_t pdu_length, 138 31 DATA_BLOB *sig) 139 32 { 140 struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data; 141 142 return ntlmssp_make_packet_signature(gensec_ntlmssp_state, sig_mem_ctx, 143 data, length, 144 whole_pdu, pdu_length, 145 NTLMSSP_SEND, sig, true); 146 } 147 148 /** 149 * Check the signature of an incoming packet 150 * 151 */ 152 153 NTSTATUS gensec_ntlmssp_check_packet(struct gensec_security *gensec_security, 154 TALLOC_CTX *sig_mem_ctx, 155 const uint8_t *data, size_t length, 156 const uint8_t *whole_pdu, size_t pdu_length, 157 const DATA_BLOB *sig) 158 { 159 struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data; 160 161 DATA_BLOB local_sig; 33 struct gensec_ntlmssp_context *gensec_ntlmssp = 34 talloc_get_type_abort(gensec_security->private_data, 35 struct gensec_ntlmssp_context); 162 36 NTSTATUS nt_status; 163 37 164 if (!gensec_ntlmssp_state->session_key.length) { 165 DEBUG(3, ("NO session key, cannot check packet signature\n")); 166 return NT_STATUS_NO_USER_SESSION_KEY; 167 } 168 169 nt_status = ntlmssp_make_packet_signature(gensec_ntlmssp_state, sig_mem_ctx, 170 data, length, 171 whole_pdu, pdu_length, 172 NTLMSSP_RECEIVE, &local_sig, true); 173 174 if (!NT_STATUS_IS_OK(nt_status)) { 175 DEBUG(0, ("NTLMSSP packet check failed with %s\n", nt_errstr(nt_status))); 176 return nt_status; 177 } 178 179 if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { 180 if (local_sig.length != sig->length || 181 memcmp(local_sig.data, 182 sig->data, sig->length) != 0) { 183 DEBUG(5, ("BAD SIG NTLM2: wanted signature over %llu bytes of input:\n", (unsigned long long)pdu_length)); 184 dump_data(5, local_sig.data, local_sig.length); 185 186 DEBUG(5, ("BAD SIG: got signature over %llu bytes of input:\n", (unsigned long long)pdu_length)); 187 dump_data(5, sig->data, sig->length); 188 189 DEBUG(1, ("NTLMSSP NTLM2 packet check failed due to invalid signature on %llu bytes of input!\n", (unsigned long long)pdu_length)); 190 return NT_STATUS_ACCESS_DENIED; 191 } 192 } else { 193 if (local_sig.length != sig->length || 194 memcmp(local_sig.data + 8, 195 sig->data + 8, sig->length - 8) != 0) { 196 DEBUG(5, ("BAD SIG NTLM1: wanted signature of %llu bytes of input:\n", (unsigned long long)length)); 197 dump_data(5, local_sig.data, local_sig.length); 198 199 DEBUG(5, ("BAD SIG: got signature of %llu bytes of input:\n", (unsigned long long)length)); 200 dump_data(5, sig->data, sig->length); 201 202 DEBUG(1, ("NTLMSSP NTLM1 packet check failed due to invalid signature on %llu bytes of input:\n", (unsigned long long)length)); 203 return NT_STATUS_ACCESS_DENIED; 204 } 205 } 206 dump_data_pw("checked ntlmssp signature\n", sig->data, sig->length); 207 208 return NT_STATUS_OK; 209 } 210 211 212 /** 213 * Seal data with the NTLMSSP algorithm 214 * 215 */ 216 217 NTSTATUS gensec_ntlmssp_seal_packet(struct gensec_security *gensec_security, 218 TALLOC_CTX *sig_mem_ctx, 219 uint8_t *data, size_t length, 220 const uint8_t *whole_pdu, size_t pdu_length, 221 DATA_BLOB *sig) 222 { 223 struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data; 224 NTSTATUS nt_status; 225 if (!gensec_ntlmssp_state->session_key.length) { 226 DEBUG(3, ("NO session key, cannot seal packet\n")); 227 return NT_STATUS_NO_USER_SESSION_KEY; 228 } 229 230 DEBUG(10,("ntlmssp_seal_data: seal\n")); 231 dump_data_pw("ntlmssp clear data\n", data, length); 232 if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { 233 /* The order of these two operations matters - we must first seal the packet, 234 then seal the sequence number - this is becouse the send_seal_hash is not 235 constant, but is is rather updated with each iteration */ 236 nt_status = ntlmssp_make_packet_signature(gensec_ntlmssp_state, sig_mem_ctx, 237 data, length, 238 whole_pdu, pdu_length, 239 NTLMSSP_SEND, sig, false); 240 arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state, data, length); 241 if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { 242 arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state, sig->data+4, 8); 243 } 244 } else { 245 uint32_t crc; 246 crc = crc32_calc_buffer(data, length); 247 if (!msrpc_gen(sig_mem_ctx, 248 sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, gensec_ntlmssp_state->crypt.ntlm.seq_num)) { 249 return NT_STATUS_NO_MEMORY; 250 } 251 252 /* The order of these two operations matters - we must 253 first seal the packet, then seal the sequence 254 number - this is becouse the ntlmssp_hash is not 255 constant, but is is rather updated with each 256 iteration */ 257 258 arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm.arcfour_state, data, length); 259 arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm.arcfour_state, sig->data+4, sig->length-4); 260 /* increment counter on send */ 261 gensec_ntlmssp_state->crypt.ntlm.seq_num++; 262 nt_status = NT_STATUS_OK; 263 } 264 dump_data_pw("ntlmssp signature\n", sig->data, sig->length); 265 dump_data_pw("ntlmssp sealed data\n", data, length); 266 38 nt_status = ntlmssp_sign_packet(gensec_ntlmssp->ntlmssp_state, 39 sig_mem_ctx, 40 data, length, 41 whole_pdu, pdu_length, 42 sig); 267 43 268 44 return nt_status; 269 45 } 270 46 271 /** 272 * Unseal data with the NTLMSSP algorithm 273 * 274 */ 47 NTSTATUS gensec_ntlmssp_check_packet(struct gensec_security *gensec_security, 48 TALLOC_CTX *sig_mem_ctx, 49 const uint8_t *data, size_t length, 50 const uint8_t *whole_pdu, size_t pdu_length, 51 const DATA_BLOB *sig) 52 { 53 struct gensec_ntlmssp_context *gensec_ntlmssp = 54 talloc_get_type_abort(gensec_security->private_data, 55 struct gensec_ntlmssp_context); 56 NTSTATUS nt_status; 57 58 nt_status = ntlmssp_check_packet(gensec_ntlmssp->ntlmssp_state, 59 data, length, 60 whole_pdu, pdu_length, 61 sig); 62 63 return nt_status; 64 } 65 66 NTSTATUS gensec_ntlmssp_seal_packet(struct gensec_security *gensec_security, 67 TALLOC_CTX *sig_mem_ctx, 68 uint8_t *data, size_t length, 69 const uint8_t *whole_pdu, size_t pdu_length, 70 DATA_BLOB *sig) 71 { 72 struct gensec_ntlmssp_context *gensec_ntlmssp = 73 talloc_get_type_abort(gensec_security->private_data, 74 struct gensec_ntlmssp_context); 75 NTSTATUS nt_status; 76 77 nt_status = ntlmssp_seal_packet(gensec_ntlmssp->ntlmssp_state, 78 sig_mem_ctx, 79 data, length, 80 whole_pdu, pdu_length, 81 sig); 82 83 return nt_status; 84 } 275 85 276 86 /* 277 87 wrappers for the ntlmssp_*() functions 278 88 */ 279 NTSTATUS gensec_ntlmssp_unseal_packet(struct gensec_security *gensec_security, 280 TALLOC_CTX *sig_mem_ctx, 281 uint8_t *data, size_t length, 282 const uint8_t *whole_pdu, size_t pdu_length, 89 NTSTATUS gensec_ntlmssp_unseal_packet(struct gensec_security *gensec_security, 90 TALLOC_CTX *sig_mem_ctx, 91 uint8_t *data, size_t length, 92 const uint8_t *whole_pdu, size_t pdu_length, 283 93 const DATA_BLOB *sig) 284 94 { 285 struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data; 286 if (!gensec_ntlmssp_state->session_key.length) { 287 DEBUG(3, ("NO session key, cannot unseal packet\n")); 288 return NT_STATUS_NO_USER_SESSION_KEY; 289 } 95 struct gensec_ntlmssp_context *gensec_ntlmssp = 96 talloc_get_type_abort(gensec_security->private_data, 97 struct gensec_ntlmssp_context); 98 NTSTATUS nt_status; 290 99 291 dump_data_pw("ntlmssp sealed data\n", data, length); 292 if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { 293 arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm2.recv_seal_arcfour_state, data, length); 294 } else { 295 arcfour_crypt_sbox(gensec_ntlmssp_state->crypt.ntlm.arcfour_state, data, length); 296 } 297 dump_data_pw("ntlmssp clear data\n", data, length); 298 return gensec_ntlmssp_check_packet(gensec_security, sig_mem_ctx, data, length, whole_pdu, pdu_length, sig); 299 } 100 nt_status = ntlmssp_unseal_packet(gensec_ntlmssp->ntlmssp_state, 101 data, length, 102 whole_pdu, pdu_length, 103 sig); 300 104 301 /** 302 Initialise the state for NTLMSSP signing. 303 */ 304 /* TODO: make this non-public */ 305 NTSTATUS ntlmssp_sign_init(struct gensec_ntlmssp_state *gensec_ntlmssp_state) 306 { 307 TALLOC_CTX *mem_ctx = talloc_new(gensec_ntlmssp_state); 308 309 if (!mem_ctx) { 310 return NT_STATUS_NO_MEMORY; 311 } 312 313 DEBUG(3, ("NTLMSSP Sign/Seal - Initialising with flags:\n")); 314 debug_ntlmssp_flags(gensec_ntlmssp_state->neg_flags); 315 316 if (gensec_ntlmssp_state->session_key.length < 8) { 317 talloc_free(mem_ctx); 318 DEBUG(3, ("NO session key, cannot intialise signing\n")); 319 return NT_STATUS_NO_USER_SESSION_KEY; 320 } 321 322 if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) 323 { 324 DATA_BLOB weak_session_key = gensec_ntlmssp_state->session_key; 325 const char *send_sign_const; 326 const char *send_seal_const; 327 const char *recv_sign_const; 328 const char *recv_seal_const; 329 330 DATA_BLOB send_seal_key; 331 DATA_BLOB recv_seal_key; 332 333 switch (gensec_ntlmssp_state->role) { 334 case NTLMSSP_CLIENT: 335 send_sign_const = CLI_SIGN; 336 send_seal_const = CLI_SEAL; 337 recv_sign_const = SRV_SIGN; 338 recv_seal_const = SRV_SEAL; 339 break; 340 case NTLMSSP_SERVER: 341 send_sign_const = SRV_SIGN; 342 send_seal_const = SRV_SEAL; 343 recv_sign_const = CLI_SIGN; 344 recv_seal_const = CLI_SEAL; 345 break; 346 default: 347 talloc_free(mem_ctx); 348 return NT_STATUS_INTERNAL_ERROR; 349 } 350 351 gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state = talloc(gensec_ntlmssp_state, struct arcfour_state); 352 NT_STATUS_HAVE_NO_MEMORY(gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state); 353 gensec_ntlmssp_state->crypt.ntlm2.recv_seal_arcfour_state = talloc(gensec_ntlmssp_state, struct arcfour_state); 354 NT_STATUS_HAVE_NO_MEMORY(gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state); 355 356 /** 357 Weaken NTLMSSP keys to cope with down-level 358 clients, servers and export restrictions. 359 360 We probably should have some parameters to control 361 this, once we get NTLM2 working. 362 */ 363 364 /* Key weakening was not performed on the master key 365 * for NTLM2 (in ntlmssp_weaken_keys()), but must be 366 * done on the encryption subkeys only. That is why 367 * we don't have this code for the ntlmv1 case. 368 */ 369 370 if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_128) { 371 372 } else if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) { 373 weak_session_key.length = 7; 374 } else { /* forty bits */ 375 weak_session_key.length = 5; 376 } 377 dump_data_pw("NTLMSSP weakend master key:\n", 378 weak_session_key.data, 379 weak_session_key.length); 380 381 /* SEND: sign key */ 382 calc_ntlmv2_key(gensec_ntlmssp_state, 383 &gensec_ntlmssp_state->crypt.ntlm2.send_sign_key, 384 gensec_ntlmssp_state->session_key, send_sign_const); 385 dump_data_pw("NTLMSSP send sign key:\n", 386 gensec_ntlmssp_state->crypt.ntlm2.send_sign_key.data, 387 gensec_ntlmssp_state->crypt.ntlm2.send_sign_key.length); 388 389 /* SEND: seal ARCFOUR pad */ 390 calc_ntlmv2_key(mem_ctx, 391 &send_seal_key, 392 weak_session_key, send_seal_const); 393 dump_data_pw("NTLMSSP send seal key:\n", 394 send_seal_key.data, 395 send_seal_key.length); 396 arcfour_init(gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state, 397 &send_seal_key); 398 dump_data_pw("NTLMSSP send sesl hash:\n", 399 gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state->sbox, 400 sizeof(gensec_ntlmssp_state->crypt.ntlm2.send_seal_arcfour_state->sbox)); 401 402 /* RECV: sign key */ 403 calc_ntlmv2_key(gensec_ntlmssp_state, 404 &gensec_ntlmssp_state->crypt.ntlm2.recv_sign_key, 405 gensec_ntlmssp_state->session_key, recv_sign_const); 406 dump_data_pw("NTLMSSP recv sign key:\n", 407 gensec_ntlmssp_state->crypt.ntlm2.recv_sign_key.data, 408 gensec_ntlmssp_state->crypt.ntlm2.recv_sign_key.length); 409 410 /* RECV: seal ARCFOUR pad */ 411 calc_ntlmv2_key(mem_ctx, 412 &recv_seal_key, 413 weak_session_key, recv_seal_const); 414 dump_data_pw("NTLMSSP recv seal key:\n", 415 recv_seal_key.data, 416 recv_seal_key.length); 417 arcfour_init(gensec_ntlmssp_state->crypt.ntlm2.recv_seal_arcfour_state, 418 &recv_seal_key); 419 dump_data_pw("NTLMSSP receive seal hash:\n", 420 gensec_ntlmssp_state->crypt.ntlm2.recv_seal_arcfour_state->sbox, 421 sizeof(gensec_ntlmssp_state->crypt.ntlm2.recv_seal_arcfour_state->sbox)); 422 423 gensec_ntlmssp_state->crypt.ntlm2.send_seq_num = 0; 424 gensec_ntlmssp_state->crypt.ntlm2.recv_seq_num = 0; 425 426 } else { 427 DATA_BLOB weak_session_key = ntlmssp_weakend_key(gensec_ntlmssp_state, mem_ctx); 428 DEBUG(5, ("NTLMSSP Sign/Seal - using NTLM1\n")); 429 430 gensec_ntlmssp_state->crypt.ntlm.arcfour_state = talloc(gensec_ntlmssp_state, struct arcfour_state); 431 NT_STATUS_HAVE_NO_MEMORY(gensec_ntlmssp_state->crypt.ntlm.arcfour_state); 432 433 arcfour_init(gensec_ntlmssp_state->crypt.ntlm.arcfour_state, 434 &weak_session_key); 435 dump_data_pw("NTLMSSP hash:\n", gensec_ntlmssp_state->crypt.ntlm.arcfour_state->sbox, 436 sizeof(gensec_ntlmssp_state->crypt.ntlm.arcfour_state->sbox)); 437 438 gensec_ntlmssp_state->crypt.ntlm.seq_num = 0; 439 } 440 441 talloc_free(mem_ctx); 442 return NT_STATUS_OK; 105 return nt_status; 443 106 } 444 107 … … 449 112 450 113 NTSTATUS gensec_ntlmssp_wrap(struct gensec_security *gensec_security, 451 TALLOC_CTX * sig_mem_ctx,114 TALLOC_CTX *out_mem_ctx, 452 115 const DATA_BLOB *in, 453 116 DATA_BLOB *out) 454 117 { 455 DATA_BLOB sig; 456 NTSTATUS nt_status; 118 struct gensec_ntlmssp_context *gensec_ntlmssp = 119 talloc_get_type_abort(gensec_security->private_data, 120 struct gensec_ntlmssp_context); 457 121 458 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) { 459 460 *out = data_blob_talloc(sig_mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE); 461 if (!out->data) { 462 return NT_STATUS_NO_MEMORY; 463 } 464 memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length); 465 466 nt_status = gensec_ntlmssp_seal_packet(gensec_security, sig_mem_ctx, 467 out->data + NTLMSSP_SIG_SIZE, 468 out->length - NTLMSSP_SIG_SIZE, 469 out->data + NTLMSSP_SIG_SIZE, 470 out->length - NTLMSSP_SIG_SIZE, 471 &sig); 472 473 if (NT_STATUS_IS_OK(nt_status)) { 474 memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE); 475 } 476 return nt_status; 477 478 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) { 479 480 *out = data_blob_talloc(sig_mem_ctx, NULL, in->length + NTLMSSP_SIG_SIZE); 481 if (!out->data) { 482 return NT_STATUS_NO_MEMORY; 483 } 484 memcpy(out->data + NTLMSSP_SIG_SIZE, in->data, in->length); 485 486 nt_status = gensec_ntlmssp_sign_packet(gensec_security, sig_mem_ctx, 487 out->data + NTLMSSP_SIG_SIZE, 488 out->length - NTLMSSP_SIG_SIZE, 489 out->data + NTLMSSP_SIG_SIZE, 490 out->length - NTLMSSP_SIG_SIZE, 491 &sig); 492 493 if (NT_STATUS_IS_OK(nt_status)) { 494 memcpy(out->data, sig.data, NTLMSSP_SIG_SIZE); 495 } 496 return nt_status; 497 498 } else { 499 *out = *in; 500 return NT_STATUS_OK; 501 } 122 return ntlmssp_wrap(gensec_ntlmssp->ntlmssp_state, 123 out_mem_ctx, 124 in, out); 502 125 } 503 126 504 127 505 128 NTSTATUS gensec_ntlmssp_unwrap(struct gensec_security *gensec_security, 506 TALLOC_CTX * sig_mem_ctx,129 TALLOC_CTX *out_mem_ctx, 507 130 const DATA_BLOB *in, 508 131 DATA_BLOB *out) 509 132 { 510 DATA_BLOB sig; 133 struct gensec_ntlmssp_context *gensec_ntlmssp = 134 talloc_get_type_abort(gensec_security->private_data, 135 struct gensec_ntlmssp_context); 511 136 512 if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) { 513 if (in->length < NTLMSSP_SIG_SIZE) { 514 return NT_STATUS_INVALID_PARAMETER; 515 } 516 sig.data = in->data; 517 sig.length = NTLMSSP_SIG_SIZE; 518 519 *out = data_blob_talloc(sig_mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE); 520 521 return gensec_ntlmssp_unseal_packet(gensec_security, sig_mem_ctx, 522 out->data, out->length, 523 out->data, out->length, 524 &sig); 525 526 } else if (gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) { 527 struct gensec_ntlmssp_state *gensec_ntlmssp_state = 528 (struct gensec_ntlmssp_state *)gensec_security->private_data; 529 NTSTATUS status; 530 uint32_t ntlm_seqnum; 531 struct arcfour_state ntlm_state; 532 uint32_t ntlm2_seqnum_r; 533 uint8_t ntlm2_key_r[16]; 534 struct arcfour_state ntlm2_state_r; 535 536 if (in->length < NTLMSSP_SIG_SIZE) { 537 return NT_STATUS_INVALID_PARAMETER; 538 } 539 sig.data = in->data; 540 sig.length = NTLMSSP_SIG_SIZE; 541 *out = data_blob_talloc(sig_mem_ctx, in->data + NTLMSSP_SIG_SIZE, in->length - NTLMSSP_SIG_SIZE); 542 543 if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { 544 ntlm2_seqnum_r = gensec_ntlmssp_state->crypt.ntlm2.recv_seq_num; 545 ntlm2_state_r = *gensec_ntlmssp_state->crypt.ntlm2.recv_seal_arcfour_state; 546 memcpy(ntlm2_key_r, 547 gensec_ntlmssp_state->crypt.ntlm2.recv_sign_key.data, 548 16); 549 } else { 550 ntlm_seqnum = gensec_ntlmssp_state->crypt.ntlm.seq_num; 551 ntlm_state = *gensec_ntlmssp_state->crypt.ntlm.arcfour_state; 552 } 553 554 status = gensec_ntlmssp_check_packet(gensec_security, sig_mem_ctx, 555 out->data, out->length, 556 out->data, out->length, 557 &sig); 558 if (!NT_STATUS_IS_OK(status)) { 559 NTSTATUS check_status = status; 560 /* 561 * The Windows LDAP libraries seems to have a bug 562 * and always use sealing even if only signing was 563 * negotiated. So we need to fallback. 564 */ 565 566 if (gensec_ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { 567 gensec_ntlmssp_state->crypt.ntlm2.recv_seq_num = ntlm2_seqnum_r; 568 *gensec_ntlmssp_state->crypt.ntlm2.recv_seal_arcfour_state = ntlm2_state_r; 569 memcpy(gensec_ntlmssp_state->crypt.ntlm2.recv_sign_key.data, 570 ntlm2_key_r, 16); 571 } else { 572 gensec_ntlmssp_state->crypt.ntlm.seq_num = ntlm_seqnum; 573 *gensec_ntlmssp_state->crypt.ntlm.arcfour_state = ntlm_state; 574 } 575 576 status = gensec_ntlmssp_unseal_packet(gensec_security, 577 sig_mem_ctx, 578 out->data, 579 out->length, 580 out->data, 581 out->length, 582 &sig); 583 if (NT_STATUS_IS_OK(status)) { 584 gensec_ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; 585 } else { 586 status = check_status; 587 } 588 } 589 return status; 590 } else { 591 *out = *in; 592 return NT_STATUS_OK; 593 } 137 return ntlmssp_unwrap(gensec_ntlmssp->ntlmssp_state, 138 out_mem_ctx, 139 in, out); 594 140 } 595
Note:
See TracChangeset
for help on using the changeset viewer.