r11511: A classic "friday night check-in" :-). This moves much
[abartlet/samba.git/.git] / source3 / smbd / negprot.c
index bdb15cb3f7cb970ce2f3097c460a4f4799844a74..db061cb1b8c0b8e3926eda13bbe9a98662217ccf 100644 (file)
 
 #include "includes.h"
 
+extern fstring remote_proto;
 extern enum protocol_types Protocol;
 extern int max_recv;
+
 BOOL global_encrypted_passwords_negotiated = False;
 BOOL global_spnego_negotiated = False;
 struct auth_context *negprot_global_auth_context = NULL;
@@ -114,9 +116,9 @@ static int reply_lanman1(char *inbuf, char *outbuf)
        SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
                readbraw writebraw (possibly) */
        SIVAL(outbuf,smb_vwv6,sys_getpid());
-       SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
+       SSVAL(outbuf,smb_vwv10, set_server_zone_offset(t)/60);
 
-       put_dos_date(outbuf,smb_vwv8,t);
+       srv_put_dos_date(outbuf,smb_vwv8,t);
 
        return (smb_len(outbuf)+4);
 }
@@ -156,8 +158,8 @@ static int reply_lanman2(char *inbuf, char *outbuf)
        SSVAL(outbuf,smb_vwv3,lp_maxmux()); 
        SSVAL(outbuf,smb_vwv4,1);
        SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
-       SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
-       put_dos_date(outbuf,smb_vwv8,t);
+       SSVAL(outbuf,smb_vwv10, set_server_zone_offset(t)/60);
+       srv_put_dos_date(outbuf,smb_vwv8,t);
 
        return (smb_len(outbuf)+4);
 }
@@ -166,18 +168,16 @@ 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)
+static int negprot_spnego(char *p, uint8 *pkeylen)
 {
        DATA_BLOB blob;
        nstring dos_name;
        fstring unix_name;
-       uint8 guid[17];
+       char guid[17];
        const char *OIDs_krb5[] = {OID_KERBEROS5,
                                   OID_KERBEROS5_OLD,
                                   OID_NTLMSSP,
                                   NULL};
-       const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
-       char *principal;
        int len;
 
        global_spnego_negotiated = True;
@@ -187,7 +187,7 @@ static int negprot_spnego(char *p)
        safe_strcpy(unix_name, global_myname(), sizeof(unix_name)-1);
        strlower_m(unix_name);
        push_ascii_nstring(dos_name, unix_name);
-       safe_strcpy((char *)guid, dos_name, sizeof(guid)-1);
+       safe_strcpy(guid, dos_name, sizeof(guid)-1);
 
 #ifdef DEVELOPER
        /* valgrind fixer... */
@@ -198,27 +198,39 @@ static int negprot_spnego(char *p)
        }
 #endif
 
-#if 0
        /* strangely enough, NT does not sent the single OID NTLMSSP when
           not a ADS member, it sends no OIDs at all
 
-          we can't do this until we teach our sesssion setup parser to know
-          about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)
+          OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know
+                  about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"
+
+          Our sessionsetup code now handles raw NTLMSSP connects, so we can go
+          back to doing what W2K3 does here. This is needed to make PocketPC 2003
+          CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
+          for details. JRA.
+
        */
-       if (lp_security() != SEC_ADS) {
+
+       if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) {
                memcpy(p, guid, 16);
+               *pkeylen = 0;
                return 16;
-       }
-#endif
-       if (lp_security() != SEC_ADS) {
-               blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
        } else {
-               asprintf(&principal, "%s$@%s", guid, lp_realm());
-               blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
-               free(principal);
+               fstring myname;
+               char *host_princ_s = NULL;
+               name_to_fqdn(myname, global_myname());
+               strlower_m(myname);
+               asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm());
+               blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s);
+               SAFE_FREE(host_princ_s);
        }
        memcpy(p, blob.data, blob.length);
        len = blob.length;
+       if (len > 256) {
+               DEBUG(0,("negprot_spnego: blob length too long (%d)\n", len));
+               len = 255;
+       }
+       *pkeylen = len;
        data_blob_free(&blob);
        return len;
 }
@@ -234,9 +246,9 @@ static int reply_nt1(char *inbuf, char *outbuf)
                CAP_LEVEL_II_OPLOCKS;
 
        int secword=0;
-       time_t t = time(NULL);
        char *p, *q;
        BOOL negotiate_spnego = False;
+       time_t t = time(NULL);
 
        global_encrypted_passwords_negotiated = lp_encrypted_passwords();
 
@@ -310,7 +322,7 @@ static int reply_nt1(char *inbuf, char *outbuf)
        SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
        SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
        put_long_date(outbuf+smb_vwv11+1,t);
-       SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
+       SSVALS(outbuf,smb_vwv15+1,set_server_zone_offset(t)/60);
        
        p = q = smb_buf(outbuf);
        if (!negotiate_spnego) {
@@ -319,16 +331,17 @@ static int reply_nt1(char *inbuf, char *outbuf)
                        /* note that we do not send a challenge at all if
                           we are using plaintext */
                        get_challenge(p);
-                       SSVALS(outbuf,smb_vwv16+1,8);
+                       SCVAL(outbuf,smb_vwv16+1,8);
                        p += 8;
                }
                p += srvstr_push(outbuf, p, lp_workgroup(), -1, 
                                 STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
                DEBUG(3,("not using SPNEGO\n"));
        } else {
-               int len = negprot_spnego(p);
+               uint8 keylen;
+               int len = negprot_spnego(p, &keylen);
                
-               SSVALS(outbuf,smb_vwv16+1,len);
+               SCVAL(outbuf,smb_vwv16+1,keylen);
                p += len;
                DEBUG(3,("using SPNEGO\n"));
        }
@@ -549,7 +562,6 @@ int reply_negprot(connection_struct *conn,
   
        SSVAL(outbuf,smb_vwv0,choice);
        if(choice != -1) {
-               extern fstring remote_proto;
                fstrcpy(remote_proto,supported_protocols[protocol].short_name);
                reload_services(True);          
                outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);