root/source4/auth/ntlmssp/ntlmssp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. debug_ntlmssp_flags
  2. gensec_ntlmssp_magic
  3. gensec_ntlmssp_update_find
  4. gensec_ntlmssp_update
  5. gensec_ntlmssp_session_key
  6. ntlmssp_handle_neg_flags
  7. ntlmssp_weakend_key
  8. gensec_ntlmssp_have_feature
  9. gensec_ntlmssp_start
  10. gensec_ntlmssp_init

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

/* [<][>][^][v][top][bottom][index][help] */