challange -> challenge
[samba.git] / source3 / smbd / negprot.c
index dc19e2bdfb3e6983aafd677745fd4abaf521449a..9cbe0fdb0af73c1b5e122c4c156c2bbab23f443b 100644 (file)
@@ -25,7 +25,9 @@ extern int Protocol;
 extern int max_recv;
 extern fstring global_myworkgroup;
 extern fstring remote_machine;
-BOOL global_encrypted_passwords_negotiated;
+BOOL global_encrypted_passwords_negotiated = False;
+BOOL global_spnego_negotiated = False;
+auth_authsupplied_info *negprot_global_auth_info = NULL;
 
 /****************************************************************************
 reply for the core protocol
@@ -67,6 +69,7 @@ static int reply_lanman1(char *inbuf, char *outbuf)
   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
   int secword=0;
   time_t t = time(NULL);
+  DATA_BLOB cryptkey;
 
   global_encrypted_passwords_negotiated = lp_encrypted_passwords();
 
@@ -76,8 +79,14 @@ static int reply_lanman1(char *inbuf, char *outbuf)
   set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
   SSVAL(outbuf,smb_vwv1,secword); 
   /* Create a token value and add it to the outgoing packet. */
-  if (global_encrypted_passwords_negotiated) 
-    generate_next_challenge(smb_buf(outbuf));
+  if (global_encrypted_passwords_negotiated) {
+         if (!make_auth_info_subsystem(&negprot_global_auth_info)) {
+                 smb_panic("cannot make_negprot_global_auth_info!\n");
+         }
+         cryptkey = auth_get_challenge(negprot_global_auth_info);
+         memcpy(smb_buf(outbuf), cryptkey.data, 8);
+         data_blob_free(&cryptkey);
+  }
 
   Protocol = PROTOCOL_LANMAN1;
 
@@ -105,40 +114,26 @@ static int reply_lanman2(char *inbuf, char *outbuf)
   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
   int secword=0;
   time_t t = time(NULL);
-  struct cli_state *cli = NULL;
-  char cryptkey[8];
-  char crypt_len = 0;
+  DATA_BLOB cryptkey;
 
   global_encrypted_passwords_negotiated = lp_encrypted_passwords();
-
-  if (lp_security() == SEC_SERVER) {
-         cli = server_cryptkey();
-  }
-
-  if (cli) {
-         DEBUG(3,("using password server validation\n"));
-         global_encrypted_passwords_negotiated = ((cli->sec_mode & 2) != 0);
-  }
-
+  
   if (lp_security()>=SEC_USER) secword |= 1;
   if (global_encrypted_passwords_negotiated) secword |= 2;
 
+  set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
+  SSVAL(outbuf,smb_vwv1,secword); 
+  SIVAL(outbuf,smb_vwv6,sys_getpid());
+
   if (global_encrypted_passwords_negotiated) {
-         crypt_len = 8;
-         if (!cli) {
-                 generate_next_challenge(cryptkey);
-         } else {
-                 memcpy(cryptkey, cli->secblob.data, 8);
-                 set_challenge(cryptkey);
+         if (!make_auth_info_subsystem(&negprot_global_auth_info)) {
+                 smb_panic("cannot make_negprot_global_auth_info!\n");
          }
+         cryptkey = auth_get_challenge(negprot_global_auth_info);
+         memcpy(smb_buf(outbuf), cryptkey.data, 8);
+         data_blob_free(&cryptkey);
   }
 
-  set_message(outbuf,13,crypt_len,True);
-  SSVAL(outbuf,smb_vwv1,secword); 
-  SIVAL(outbuf,smb_vwv6,sys_getpid());
-  if (global_encrypted_passwords_negotiated) 
-         memcpy(smb_buf(outbuf), cryptkey, 8);
-
   Protocol = PROTOCOL_LANMAN2;
 
   /* Reply, SMBlockread, SMBwritelock supported. */
@@ -158,26 +153,36 @@ static int reply_lanman2(char *inbuf, char *outbuf)
 /* 
    generate the spnego negprot reply blob. Return the number of bytes used
 */
-static int negprot_spnego(char *p, uint8 cryptkey[8])
+static int negprot_spnego(char *p)
 {
        DATA_BLOB blob;
        extern pstring global_myname;
        uint8 guid[16];
        const char *OIDs[] = {OID_NTLMSSP,
                              OID_KERBEROS5,
+                             OID_KERBEROS5_OLD,
                              NULL};
-       char *principle;
+       char *principal;
        int len;
 
+       global_spnego_negotiated = True;
+
        memset(guid, 0, 16);
-       safe_strcpy(guid, global_myname, 16);
-       strlower(guid);
+       safe_strcpy((char *)guid, global_myname, 16);
+       strlower((char *)guid);
+
+       /* strangely enough, NT does not sent the single OID NTLMSSP when
+          not a ADS member, it sends no OIDs at all */
+       if (lp_security() != SEC_ADS) {
+               memcpy(p, guid, 16);
+               return 16;
+       }
 
        /* win2000 uses host$@REALM, which we will probably use eventually,
           but for now this works */
-       asprintf(&principle, "HOST/%s@%s", guid, lp_realm());
-       blob = spnego_gen_negTokenInit(guid, OIDs, principle);
-       free(principle);
+       asprintf(&principal, "HOST/%s@%s", guid, lp_realm());
+       blob = spnego_gen_negTokenInit(guid, OIDs, principal);
+       free(principal);
 
        memcpy(p, blob.data, blob.length);
        len = blob.length;
@@ -198,44 +203,22 @@ static int reply_nt1(char *inbuf, char *outbuf)
 
        int secword=0;
        time_t t = time(NULL);
-       struct cli_state *cli = NULL;
-       uint8 cryptkey[8];
+       DATA_BLOB cryptkey;
        char *p, *q;
        BOOL negotiate_spnego = False;
 
        global_encrypted_passwords_negotiated = lp_encrypted_passwords();
 
-       if (lp_security() == SEC_SERVER) {
-               DEBUG(5,("attempting password server validation\n"));
-               cli = server_cryptkey();
-       } else {
-               DEBUG(5,("not attempting password server validation\n"));
-               /* do spnego in user level security if the client
-                  supports it and we can do encrypted passwords */
-               if (global_encrypted_passwords_negotiated && 
-                   lp_security() == SEC_USER &&
-                   (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
-                       negotiate_spnego = True;
-                       capabilities |= CAP_EXTENDED_SECURITY;
-               }
-       }
+       /* do spnego in user level security if the client
+          supports it and we can do encrypted passwords */
        
-       if (cli) {
-               DEBUG(3,("using password server validation\n"));
-               global_encrypted_passwords_negotiated = ((cli->sec_mode & 2) != 0);
-       } else {
-               DEBUG(3,("not using password server validation\n"));
+       if (global_encrypted_passwords_negotiated && 
+           (lp_security() != SEC_SHARE) &&
+           (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
+               negotiate_spnego = True;
+               capabilities |= CAP_EXTENDED_SECURITY;
        }
        
-       if (global_encrypted_passwords_negotiated) {
-               if (!cli) {
-                       generate_next_challenge(cryptkey);
-               } else {
-                       memcpy(cryptkey, cli->secblob.data, 8);
-                       set_challenge(cryptkey);
-               }
-       }
-
        capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
        
        if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64)) {
@@ -278,16 +261,26 @@ static int reply_nt1(char *inbuf, char *outbuf)
        
        p = q = smb_buf(outbuf);
        if (!negotiate_spnego) {
-               if (global_encrypted_passwords_negotiated) memcpy(p, cryptkey, 8);
+               if (global_encrypted_passwords_negotiated) { 
+                       if (!make_auth_info_subsystem(&negprot_global_auth_info)) {
+                               smb_panic("cannot make_negprot_global_auth_info!\n");
+                       }
+                       cryptkey = auth_get_challenge(negprot_global_auth_info);
+                       memcpy(p, cryptkey.data, 8);
+                       data_blob_free(&cryptkey);
+               }
                SSVALS(outbuf,smb_vwv16+1,8);
                p += 8;
+               p += srvstr_push(outbuf, p, global_myworkgroup, -1, 
+                                STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
+               DEBUG(3,("not using SPNEGO\n"));
        } else {
-               int len = negprot_spnego(p, cryptkey);
+               int len = negprot_spnego(p);
+               
                SSVALS(outbuf,smb_vwv16+1,len);
                p += len;
+               DEBUG(3,("using SPNEGO\n"));
        }
-       p += srvstr_push(outbuf, p, global_myworkgroup, -1, 
-                        STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
        
        SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
        set_message_end(outbuf, p);
@@ -459,11 +452,6 @@ int reply_negprot(connection_struct *conn,
   /* possibly reload - change of architecture */
   reload_services(True);      
     
-  /* a special case to stop password server loops */
-  if (Index == 1 && strequal(remote_machine,myhostname()) && 
-      (lp_security()==SEC_SERVER || lp_security()==SEC_DOMAIN))
-    exit_server("Password server loop!");
-  
   /* Check for protocols, most desirable first */
   for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
     {
@@ -500,3 +488,4 @@ int reply_negprot(connection_struct *conn,
   END_PROFILE(SMBnegprot);
   return(outsize);
 }
+