This looks like a big change but really isn't.
[samba.git] / source3 / smbd / reply.c
index 116542ba340213137b0c998b86cc56bf4363b234..fe1de65be39d800a4604e989383834d625d393ca 100644 (file)
@@ -2,7 +2,7 @@
    Unix SMB/Netbios implementation.
    Version 1.9.
    Main SMB reply routines
-   Copyright (C) Andrew Tridgell 1992-1997
+   Copyright (C) Andrew Tridgell 1992-1998
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -41,7 +41,7 @@ extern BOOL case_sensitive;
 extern BOOL case_preserve;
 extern BOOL short_case_preserve;
 extern pstring sesssetup_user;
-extern fstring myworkgroup;
+extern fstring global_myworkgroup;
 extern int Client;
 extern int global_oplock_break;
 
@@ -55,9 +55,9 @@ report a possible attack via the password buffer overflow bug
 ****************************************************************************/
 static void overflow_attack(int len)
 {
-       DEBUG(0,("ERROR: Invalid password length %d\n", len));
+       DEBUG(0,("%s: ERROR: Invalid password length %d\n", timestring(), len));
        DEBUG(0,("your machine may be under attack by a user exploiting an old bug\n"));
-       DEBUG(0,("Attack was from IP=%s\n", client_addr()));
+       DEBUG(0,("Attack was from IP=%s\n", client_addr(Client)));
        exit_server("possible attack");
 }
 
@@ -73,7 +73,6 @@ int reply_special(char *inbuf,char *outbuf)
        pstring name1,name2;
        extern fstring remote_machine;
        extern fstring local_machine;
-       char *p;
        int len;
        char name_type = 0;
        
@@ -96,21 +95,18 @@ int reply_special(char *inbuf,char *outbuf)
                         name1,name2));      
 
                fstrcpy(remote_machine,name2);
+               remote_machine[15] = 0;
                trim_string(remote_machine," "," ");
-               p = strchr(remote_machine,' ');
                strlower(remote_machine);
-               if (p) *p = 0;
 
                fstrcpy(local_machine,name1);
-               trim_string(local_machine," "," ");
                len = strlen(local_machine);
                if (len == 16) {
                        name_type = local_machine[15];
                        local_machine[15] = 0;
                }
-               p = strchr(local_machine,' ');
+               trim_string(local_machine," "," ");
                strlower(local_machine);
-               if (p) *p = 0;
 
                if (name_type == 'R') {
                        /* We are being asked for a pathworks session --- 
@@ -124,6 +120,10 @@ int reply_special(char *inbuf,char *outbuf)
                reload_services(True);
                reopen_logs();
 
+               if (lp_status(-1)) {
+                       claim_connection(-1,"STATUS.",MAXSTATUS,True);
+               }
+
                break;
                
        case 0x89: /* session keepalive request 
@@ -217,7 +217,7 @@ static void parse_connect(char *p,char *service,char *user,
 /****************************************************************************
   reply to a tcon
 ****************************************************************************/
-int reply_tcon(char *inbuf,char *outbuf)
+int reply_tcon(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring service;
   pstring user;
@@ -260,7 +260,6 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   int connection_num;
   uint16 vuid = SVAL(inbuf,smb_uid);
   int passlen = SVAL(inbuf,smb_vwv3);
-  BOOL doencrypt = SMBENCRYPT();
 
   *service = *user = *password = *devicename = 0;
 
@@ -279,7 +278,7 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
     password[passlen]=0;    
     path = smb_buf(inbuf) + passlen;
 
-    if (!doencrypt || passlen != 24) {
+    if (passlen != 24) {
       if (strequal(password," "))
        *password = 0;
       passlen = strlen(password);
@@ -313,7 +312,7 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   }
   else
   {
-    char *fsname = "SAMBA";
+    char *fsname = FSTYPE_STRING;
     char *p;
 
     set_message(outbuf,3,3,True);
@@ -359,7 +358,7 @@ int reply_unknown(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to an ioctl
 ****************************************************************************/
-int reply_ioctl(char *inbuf,char *outbuf)
+int reply_ioctl(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   DEBUG(3,("ignoring ioctl\n"));
 #if 0
@@ -371,6 +370,75 @@ int reply_ioctl(char *inbuf,char *outbuf)
 #endif
 }
 
+/****************************************************************************
+ always return an error: it's just a matter of which one...
+ ****************************************************************************/
+static int session_trust_account(char *inbuf, char *outbuf, char *user,
+                                char *smb_passwd, int smb_passlen,
+                                char *smb_nt_passwd, int smb_nt_passlen)
+{
+  struct smb_passwd *smb_trust_acct = NULL; /* check if trust account exists */
+  if (lp_security() == SEC_USER)
+  {
+    smb_trust_acct = getsmbpwnam(user);
+  }
+  else
+  {
+    DEBUG(0,("session_trust_account: Trust account %s only supported with security = user\n", user));
+    SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+    return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
+  }
+
+  if (smb_trust_acct == NULL)
+  {
+    /* lkclXXXX: workstation entry doesn't exist */
+    DEBUG(0,("session_trust_account: Trust account %s user doesn't exist\n",user));
+    SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+    return(ERROR(0, 0xc0000000|NT_STATUS_NO_SUCH_USER));
+  }
+  else
+  {
+    if ((smb_passlen != 24) || (smb_nt_passlen != 24))
+    {
+      DEBUG(0,("session_trust_account: Trust account %s - password length wrong.\n", user));
+      SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+      return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
+    }
+
+    if (!smb_password_ok(smb_trust_acct, smb_passwd, smb_nt_passwd))
+    {
+      DEBUG(0,("session_trust_account: Trust Account %s - password failed\n", user));
+      SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+      return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
+    }
+
+    if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_DOMTRUST))
+    {
+      DEBUG(0,("session_trust_account: Domain trust account %s denied by server\n",user));
+      SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+      return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT));
+    }
+
+    if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_SVRTRUST))
+    {
+      DEBUG(0,("session_trust_account: Server trust account %s denied by server\n",user));
+      SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+      return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT));
+    }
+
+    if (IS_BITS_SET_ALL(smb_trust_acct->acct_ctrl, ACB_WSTRUST))
+    {
+      DEBUG(4,("session_trust_account: Wksta trust account %s denied by server\n", user));
+      SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+      return(ERROR(0, 0xc0000000|NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT));
+    }
+  }
+
+  /* don't know what to do: indicate logon failure */
+  SSVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
+  return(ERROR(0, 0xc0000000|NT_STATUS_LOGON_FAILURE));
+}
+
 
 /****************************************************************************
 reply to a session setup command
@@ -391,7 +459,6 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   BOOL valid_nt_password = False;
   pstring user;
   BOOL guest=False;
-  BOOL computer_id=False;
   static BOOL done_sesssetup = False;
   BOOL doencrypt = SMBENCRYPT();
   char *domain = "";
@@ -412,9 +479,10 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
     }
 
     memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
+    smb_apasswd[smb_apasslen] = 0;
     pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
 
-    if (lp_security() != SEC_SERVER && !doencrypt) {
+    if (!doencrypt && (lp_security() != SEC_SERVER)) {
            smb_apasslen = strlen(smb_apasswd);
     }
   } else {
@@ -448,12 +516,18 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
     passlen1 = MIN(passlen1, MAX_PASS_LEN);
     passlen2 = MIN(passlen2, MAX_PASS_LEN);
 
-    if(doencrypt) {
+#ifdef DOMAIN_CLIENT
+    if(doencrypt || ((lp_security() == SEC_SERVER) || (lp_security() == SEC_DOMAIN))) {
+#else /* DOMAIN_CLIENT */
+    if(doencrypt || lp_security() == SEC_SERVER) {
+#endif /* DOMAIN_CLIENT */
       /* Save the lanman2 password and the NT md4 password. */
       smb_apasslen = passlen1;
       memcpy(smb_apasswd,p,smb_apasslen);
+      smb_apasswd[smb_apasslen] = 0;
       smb_ntpasslen = passlen2;
       memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
+      smb_ntpasswd[smb_ntpasslen] = 0;
     } else {
       /* both Win95 and WinNT stuff up the password lengths for
         non-encrypting systems. Uggh. 
@@ -498,35 +572,13 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   /* If name ends in $ then I think it's asking about whether a */
   /* computer with that name (minus the $) has access. For now */
   /* say yes to everything ending in $. */
-  if (user[strlen(user) - 1] == '$') {
-#ifdef NTDOMAIN
-    struct smb_passwd *smb_pass; /* To check if machine account exists */
-/* 
-   PAXX: Ack. We don't want to do this. The workstation trust account
-   with a $ on the end should exist in the local password database
-   or be mapped to something generic, but not modified. For NT
-   domain support we must reject this used in certain circumstances
-   with a code to indicate to the client that it is an invalid use
-   of a workstation trust account. NTWKS needs this error to join
-   a domain. This may be the source of future bugs if we cannot
-   be sure whether to reject this or not.
-*/
-   smb_pass = get_smbpwnam(user);
-   if(smb_pass)
-   {
-     /* PAXX: This is the NO LOGON workstation trust account stuff */
-     DEBUG(4,("Rejecting workstation trust account %s",user));
-     SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */
-     CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */
-     return(ERROR(NT_STATUS_ALLOTTED_SPACE_EXCEEDED, 0xc000)); /* 0x99 NT error, 0xc00 */
-   }
-   computer_id = True;
-#else /* not NTDOMAIN, leave this in. PAXX: Someone get rid of this */
-    user[strlen(user) - 1] = '\0';
-#endif
+  if ((user[strlen(user) - 1] == '$') && (smb_apasslen == 24) && (smb_ntpasslen == 24))
+  {
+    return session_trust_account(inbuf, outbuf, user, 
+                                 smb_apasswd, smb_apasslen,
+                                 smb_ntpasswd, smb_ntpasslen);
   }
 
-
   /* If no username is sent use the guest account */
   if (!*user)
     {
@@ -556,6 +608,12 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
                  server_validate(user, domain, 
                                  smb_apasswd, smb_apasslen, 
                                  smb_ntpasswd, smb_ntpasslen)) &&
+#ifdef DOMAIN_CLIENT
+                !(lp_security() == SEC_DOMAIN &&
+                  domain_client_validate(user, domain,
+                                  smb_apasswd, smb_apasslen,
+                                  smb_ntpasswd, smb_ntpasslen)) &&
+#endif /* DOMAIN_CLIENT */
       !check_hosts_equiv(user))
     {
 
@@ -572,7 +630,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
        } 
       if (!valid_nt_password && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
        {
-         if (!computer_id && lp_security() >= SEC_USER) {
+         if (lp_security() >= SEC_USER) {
 #if (GUEST_SESSSETUP == 0)
            return(ERROR(ERRSRV,ERRbadpw));
 #endif
@@ -613,7 +671,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
     p = smb_buf(outbuf);
     strcpy(p,"Unix"); p = skip_string(p,1);
     strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
-    strcpy(p,myworkgroup); p = skip_string(p,1);
+    strcpy(p,global_myworkgroup); p = skip_string(p,1);
     set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
     /* perhaps grab OS version here?? */
   }
@@ -632,7 +690,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
     uid = pw->pw_uid;
   }
 
-  if (guest && !computer_id)
+  if (guest)
     SSVAL(outbuf,smb_vwv2,1);
 
   /* register the name and uid as being validated, so further connections
@@ -656,7 +714,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
 /****************************************************************************
   reply to a chkpth
 ****************************************************************************/
-int reply_chkpth(char *inbuf,char *outbuf)
+int reply_chkpth(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int outsize = 0;
   int cnum,mode;
@@ -711,7 +769,7 @@ int reply_chkpth(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a getatr
 ****************************************************************************/
-int reply_getatr(char *inbuf,char *outbuf)
+int reply_getatr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring fname;
   int cnum;
@@ -768,7 +826,10 @@ int reply_getatr(char *inbuf,char *outbuf)
   outsize = set_message(outbuf,10,0,True);
 
   SSVAL(outbuf,smb_vwv0,mode);
-  put_dos_date3(outbuf,smb_vwv1,mtime);
+  if(lp_dos_filetime_resolution(SNUM(cnum)) )
+    put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
+  else
+    put_dos_date3(outbuf,smb_vwv1,mtime);
   SIVAL(outbuf,smb_vwv3,size);
 
   if (Protocol >= PROTOCOL_NT1) {
@@ -788,7 +849,7 @@ int reply_getatr(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a setatr
 ****************************************************************************/
-int reply_setatr(char *inbuf,char *outbuf)
+int reply_setatr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring fname;
   int cnum;
@@ -835,7 +896,7 @@ int reply_setatr(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a dskattr
 ****************************************************************************/
-int reply_dskattr(char *inbuf,char *outbuf)
+int reply_dskattr(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int cnum;
   int outsize = 0;
@@ -862,7 +923,7 @@ int reply_dskattr(char *inbuf,char *outbuf)
   reply to a search
   Can be called from SMBsearch, SMBffirst or SMBfunique.
 ****************************************************************************/
-int reply_search(char *inbuf,char *outbuf)
+int reply_search(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring mask;
   pstring directory;
@@ -1023,9 +1084,7 @@ int reply_search(char *inbuf,char *outbuf)
          if ((dirtype&0x1F) == aVOLID)
            {     
              memcpy(p,status,21);
-             mode = aVOLID;
-             if(!CAN_WRITE(cnum)) mode |= aRONLY;
-             make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,mode,0);
+             make_dir_struct(p,"???????????",volume_label(SNUM(cnum)),0,aVOLID,0);
              dptr_fill(p+12,dptr_num);
              if (dptr_zero(p+12) && (status_len==0))
                numentries = 1;
@@ -1110,7 +1169,7 @@ int reply_search(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a fclose (stop directory search)
 ****************************************************************************/
-int reply_fclose(char *inbuf,char *outbuf)
+int reply_fclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int cnum;
   int outsize = 0;
@@ -1147,7 +1206,7 @@ int reply_fclose(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to an open
 ****************************************************************************/
-int reply_open(char *inbuf,char *outbuf)
+int reply_open(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring fname;
   int cnum;
@@ -1182,6 +1241,7 @@ int reply_open(char *inbuf,char *outbuf)
       unix_ERR_class = ERRDOS;
       unix_ERR_code = ERRbadpath;
     }
+    Files[fnum].reserved = False;
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
  
@@ -1199,6 +1259,7 @@ int reply_open(char *inbuf,char *outbuf)
       unix_ERR_class = ERRDOS;
       unix_ERR_code = ERRbadpath;
     }
+    Files[fnum].reserved = False;
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
 
@@ -1220,7 +1281,10 @@ int reply_open(char *inbuf,char *outbuf)
   outsize = set_message(outbuf,7,0,True);
   SSVAL(outbuf,smb_vwv0,fnum);
   SSVAL(outbuf,smb_vwv1,fmode);
-  put_dos_date3(outbuf,smb_vwv2,mtime);
+  if(lp_dos_filetime_resolution(SNUM(cnum)) )
+    put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
+  else
+    put_dos_date3(outbuf,smb_vwv2,mtime);
   SIVAL(outbuf,smb_vwv4,size);
   SSVAL(outbuf,smb_vwv6,rmode);
 
@@ -1244,7 +1308,11 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   int fnum = -1;
   int smb_mode = SVAL(inbuf,smb_vwv3);
   int smb_attr = SVAL(inbuf,smb_vwv5);
-  BOOL oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
+  /* Breakout the oplock request bits so we can set the
+     reply bits separately. */
+  BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
+  BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
+  BOOL oplock_request = ex_oplock_request | core_oplock_request;
 #if 0
   int open_flags = SVAL(inbuf,smb_vwv2);
   int smb_sattr = SVAL(inbuf,smb_vwv4); 
@@ -1278,6 +1346,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
       unix_ERR_class = ERRDOS;
       unix_ERR_code = ERRbadpath;
     }
+    Files[fnum].reserved = False;
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
 
@@ -1295,6 +1364,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
       unix_ERR_class = ERRDOS;
       unix_ERR_code = ERRbadpath;
     }
+    Files[fnum].reserved = False;
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
 
@@ -1311,20 +1381,39 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
     return(ERROR(ERRDOS,ERRnoaccess));
   }
 
-  if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
+  /* If the caller set the extended oplock request bit
+     and we granted one (by whatever means) - set the
+     correct bit for extended oplock reply.
+   */
+
+  if (ex_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
     smb_action |= EXTENDED_OPLOCK_GRANTED;
-    CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
   }
 
-  if(fsp->granted_oplock) {
+  if(ex_oplock_request && fsp->granted_oplock) {
     smb_action |= EXTENDED_OPLOCK_GRANTED;
+  }
+
+  /* If the caller set the core oplock request bit
+     and we granted one (by whatever means) - set the
+     correct bit for core oplock reply.
+   */
+
+  if (core_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
+    CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
+  }
+
+  if(core_oplock_request && fsp->granted_oplock) {
     CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
   }
 
   set_message(outbuf,15,0,True);
   SSVAL(outbuf,smb_vwv2,fnum);
   SSVAL(outbuf,smb_vwv3,fmode);
-  put_dos_date3(outbuf,smb_vwv4,mtime);
+  if(lp_dos_filetime_resolution(SNUM(cnum)) )
+    put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
+  else
+    put_dos_date3(outbuf,smb_vwv4,mtime);
   SIVAL(outbuf,smb_vwv6,size);
   SSVAL(outbuf,smb_vwv8,rmode);
   SSVAL(outbuf,smb_vwv11,smb_action);
@@ -1352,7 +1441,7 @@ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
   if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
     int i;
     for (i=0;i<MAX_OPEN_FILES;i++)
-      if (Files[i].uid == vuser->uid && Files[i].open) {
+      if ((Files[i].vuid == vuid) && Files[i].open) {
        close_file(i,False);
       }
   }
@@ -1370,7 +1459,7 @@ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
 /****************************************************************************
   reply to a mknew or a create
 ****************************************************************************/
-int reply_mknew(char *inbuf,char *outbuf)
+int reply_mknew(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring fname;
   int cnum,com;
@@ -1408,6 +1497,7 @@ int reply_mknew(char *inbuf,char *outbuf)
       unix_ERR_class = ERRDOS;
       unix_ERR_code = ERRbadpath;
     }
+    Files[fnum].reserved = False;
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
 
@@ -1435,6 +1525,7 @@ int reply_mknew(char *inbuf,char *outbuf)
       unix_ERR_class = ERRDOS;
       unix_ERR_code = ERRbadpath;
     }
+    Files[fnum].reserved = False;
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
  
@@ -1458,7 +1549,7 @@ int reply_mknew(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a create temporary file
 ****************************************************************************/
-int reply_ctemp(char *inbuf,char *outbuf)
+int reply_ctemp(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring fname;
   pstring fname2;
@@ -1490,6 +1581,7 @@ int reply_ctemp(char *inbuf,char *outbuf)
       unix_ERR_class = ERRDOS;
       unix_ERR_code = ERRbadpath;
     }
+    Files[fnum].reserved = False;
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
 
@@ -1509,6 +1601,7 @@ int reply_ctemp(char *inbuf,char *outbuf)
       unix_ERR_class = ERRDOS;
       unix_ERR_code = ERRbadpath;
     }
+    Files[fnum].reserved = False;
     return(UNIXERROR(ERRDOS,ERRnoaccess));
   }
 
@@ -1549,14 +1642,14 @@ static BOOL can_delete(char *fname,int cnum,int dirtype)
   }
   if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
     return(False);
-  if (!check_file_sharing(cnum,fname)) return(False);
+  if (!check_file_sharing(cnum,fname,False)) return(False);
   return(True);
 }
 
 /****************************************************************************
   reply to a unlink
 ****************************************************************************/
-int reply_unlink(char *inbuf,char *outbuf)
+int reply_unlink(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int outsize = 0;
   pstring name;
@@ -1593,7 +1686,7 @@ int reply_unlink(char *inbuf,char *outbuf)
   }
 
   if (is_mangled(mask))
-    check_mangled_stack(mask);
+    check_mangled_cache( mask );
 
   has_wild = strchr(mask,'*') || strchr(mask,'?');
 
@@ -1661,7 +1754,7 @@ int reply_unlink(char *inbuf,char *outbuf)
 /****************************************************************************
    reply to a readbraw (core+ protocol)
 ****************************************************************************/
-int reply_readbraw(char *inbuf, char *outbuf)
+int reply_readbraw(char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
 {
   int cnum,maxcount,mincount,fnum;
   int nread = 0;
@@ -1771,7 +1864,7 @@ int reply_readbraw(char *inbuf, char *outbuf)
 /****************************************************************************
   reply to a lockread (core+ protocol)
 ****************************************************************************/
-int reply_lockread(char *inbuf,char *outbuf)
+int reply_lockread(char *inbuf,char *outbuf, int dum_size, int dum_buffsiz)
 {
   int cnum,fnum;
   int nread = -1;
@@ -1817,7 +1910,7 @@ int reply_lockread(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a read
 ****************************************************************************/
-int reply_read(char *inbuf,char *outbuf)
+int reply_read(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int cnum,numtoread,fnum;
   int nread = 0;
@@ -1876,6 +1969,10 @@ int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
 
   cnum = SVAL(inbuf,smb_tid);
 
+  /* If it's an IPC, pass off the pipe handler. */
+  if (IS_IPC(cnum))
+    return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
+
   CHECK_FNUM(fnum,cnum);
   CHECK_READ(fnum);
   CHECK_ERROR(fnum);
@@ -1908,7 +2005,7 @@ int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
 /****************************************************************************
   reply to a writebraw (core+ or LANMAN1.0 protocol)
 ****************************************************************************/
-int reply_writebraw(char *inbuf,char *outbuf)
+int reply_writebraw(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int nwritten=0;
   int total_written=0;
@@ -2015,7 +2112,7 @@ int reply_writebraw(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a writeunlock (core+)
 ****************************************************************************/
-int reply_writeunlock(char *inbuf,char *outbuf)
+int reply_writeunlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int cnum,fnum;
   int nwritten = -1;
@@ -2072,7 +2169,7 @@ int reply_writeunlock(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a write
 ****************************************************************************/
-int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
+int reply_write(char *inbuf,char *outbuf,int dum_size,int dum_buffsize)
 {
   int cnum,numtowrite,fnum;
   int nwritten = -1;
@@ -2080,9 +2177,6 @@ int reply_write(char *inbuf,char *outbuf,int dum1,int dum2)
   int startpos;
   char *data;
 
-  dum1 = dum2 = 0;
-
-  
   cnum = SVAL(inbuf,smb_tid);
   fnum = GETFNUM(inbuf,smb_vwv0);
 
@@ -2190,7 +2284,7 @@ int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
 /****************************************************************************
   reply to a lseek
 ****************************************************************************/
-int reply_lseek(char *inbuf,char *outbuf)
+int reply_lseek(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int cnum,fnum;
   uint32 startpos;
@@ -2231,7 +2325,7 @@ int reply_lseek(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a flush
 ****************************************************************************/
-int reply_flush(char *inbuf,char *outbuf)
+int reply_flush(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int cnum, fnum;
   int outsize = set_message(outbuf,0,0,True);
@@ -2262,7 +2356,7 @@ int reply_flush(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a exit
 ****************************************************************************/
-int reply_exit(char *inbuf,char *outbuf)
+int reply_exit(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int outsize = set_message(outbuf,0,0,True);
   DEBUG(3,("%s exit\n",timestring()));
@@ -2274,7 +2368,7 @@ int reply_exit(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a close
 ****************************************************************************/
-int reply_close(char *inbuf,char *outbuf)
+int reply_close(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int fnum,cnum;
   int outsize = 0;
@@ -2303,16 +2397,16 @@ int reply_close(char *inbuf,char *outbuf)
   /* try and set the date */
   set_filetime(cnum, Files[fnum].name,mtime);
 
+  DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
+          timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
+          Connections[cnum].num_files_open));
+  
   close_file(fnum,True);
 
   /* We have a cached error */
   if(eclass || err)
     return(ERROR(eclass,err));
 
-  DEBUG(3,("%s close fd=%d fnum=%d cnum=%d (numopen=%d)\n",
-          timestring(),Files[fnum].fd_ptr->fd,fnum,cnum,
-          Connections[cnum].num_files_open));
-  
   return(outsize);
 }
 
@@ -2320,7 +2414,7 @@ int reply_close(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a writeclose (Core+ protocol)
 ****************************************************************************/
-int reply_writeclose(char *inbuf,char *outbuf)
+int reply_writeclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int cnum,numtowrite,fnum;
   int nwritten = -1;
@@ -2369,7 +2463,7 @@ int reply_writeclose(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a lock
 ****************************************************************************/
-int reply_lock(char *inbuf,char *outbuf)
+int reply_lock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int fnum,cnum;
   int outsize = set_message(outbuf,0,0,True);
@@ -2398,7 +2492,7 @@ int reply_lock(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a unlock
 ****************************************************************************/
-int reply_unlock(char *inbuf,char *outbuf)
+int reply_unlock(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int fnum,cnum;
   int outsize = set_message(outbuf,0,0,True);
@@ -2427,7 +2521,7 @@ int reply_unlock(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a tdis
 ****************************************************************************/
-int reply_tdis(char *inbuf,char *outbuf)
+int reply_tdis(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int cnum;
   int outsize = set_message(outbuf,0,0,True);
@@ -2455,7 +2549,7 @@ int reply_tdis(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a echo
 ****************************************************************************/
-int reply_echo(char *inbuf,char *outbuf)
+int reply_echo(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int cnum;
   int smb_reverb = SVAL(inbuf,smb_vwv0);
@@ -2505,7 +2599,7 @@ int reply_echo(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a printopen
 ****************************************************************************/
-int reply_printopen(char *inbuf,char *outbuf)
+int reply_printopen(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring fname;
   pstring fname2;
@@ -2543,15 +2637,19 @@ int reply_printopen(char *inbuf,char *outbuf)
 
   strcpy(fname2,(char *)mktemp(fname));
 
-  if (!check_name(fname2,cnum))
-    return(ERROR(ERRDOS,ERRnoaccess));
+  if (!check_name(fname2,cnum)) {
+         Files[fnum].reserved = False;
+         return(ERROR(ERRDOS,ERRnoaccess));
+  }
 
   /* Open for exclusive use, write only. */
   open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), 
                    0, NULL, NULL);
 
-  if (!Files[fnum].open)
-    return(UNIXERROR(ERRDOS,ERRnoaccess));
+  if (!Files[fnum].open) {
+         Files[fnum].reserved = False;
+         return(UNIXERROR(ERRDOS,ERRnoaccess));
+  }
 
   /* force it to be a print file */
   Files[fnum].print_file = True;
@@ -2568,7 +2666,7 @@ int reply_printopen(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a printclose
 ****************************************************************************/
-int reply_printclose(char *inbuf,char *outbuf)
+int reply_printclose(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int fnum,cnum;
   int outsize = set_message(outbuf,0,0,True);
@@ -2582,10 +2680,10 @@ int reply_printclose(char *inbuf,char *outbuf)
   if (!CAN_PRINT(cnum))
     return(ERROR(ERRDOS,ERRnoaccess));
   
-  close_file(fnum,True);
-  
   DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
   
+  close_file(fnum,True);
+
   return(outsize);
 }
 
@@ -2593,7 +2691,7 @@ int reply_printclose(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a printqueue
 ****************************************************************************/
-int reply_printqueue(char *inbuf,char *outbuf)
+int reply_printqueue(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int cnum;
   int outsize = set_message(outbuf,2,3,True);
@@ -2687,7 +2785,7 @@ int reply_printqueue(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a printwrite
 ****************************************************************************/
-int reply_printwrite(char *inbuf,char *outbuf)
+int reply_printwrite(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int cnum,numtowrite,fnum;
   int outsize = set_message(outbuf,0,0,True);
@@ -2719,7 +2817,7 @@ int reply_printwrite(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a mkdir
 ****************************************************************************/
-int reply_mkdir(char *inbuf,char *outbuf)
+int reply_mkdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring directory;
   int cnum;
@@ -2814,7 +2912,7 @@ static BOOL recursive_rmdir(char *directory)
 /****************************************************************************
   reply to a rmdir
 ****************************************************************************/
-int reply_rmdir(char *inbuf,char *outbuf)
+int reply_rmdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring directory;
   int cnum;
@@ -2998,7 +3096,7 @@ static BOOL can_rename(char *fname,int cnum)
   if (!CAN_WRITE(cnum)) return(False);
 
   if (sys_lstat(fname,&sbuf) != 0) return(False);
-  if (!check_file_sharing(cnum,fname)) return(False);
+  if (!check_file_sharing(cnum,fname,True)) return(False);
 
   return(True);
 }
@@ -3006,7 +3104,7 @@ static BOOL can_rename(char *fname,int cnum)
 /****************************************************************************
   reply to a mv
 ****************************************************************************/
-int reply_mv(char *inbuf,char *outbuf)
+int reply_mv(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int outsize = 0;
   pstring name;
@@ -3055,7 +3153,7 @@ int reply_mv(char *inbuf,char *outbuf)
   }
 
   if (is_mangled(mask))
-    check_mangled_stack(mask);
+    check_mangled_cache( mask );
 
   has_wild = strchr(mask,'*') || strchr(mask,'?');
 
@@ -3147,14 +3245,23 @@ int reply_mv(char *inbuf,char *outbuf)
 
            error = ERRnoaccess;
            sprintf(fname,"%s/%s",directory,dname);
-           if (!can_rename(fname,cnum)) continue;
+           if (!can_rename(fname,cnum)) {
+                   DEBUG(6,("rename %s refused\n", fname));
+                   continue;
+           }
            pstrcpy(destname,newname);
 
-           if (!resolve_wildcards(fname,destname)) continue;
+           if (!resolve_wildcards(fname,destname)) {
+                   DEBUG(6,("resolve_wildcards %s %s failed\n", 
+                            fname, destname));
+                   continue;
+           }
 
            if (file_exist(destname,NULL)) {
-             error = 183;
-             continue;
+                   DEBUG(6,("file_exist %s\n", 
+                            destname));
+                   error = 183;
+                   continue;
            }
            if (!sys_rename(fname,destname)) count++;
            DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
@@ -3212,7 +3319,10 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
   open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
                   1,0,0,&Access,&action);
 
-  if (!Files[fnum1].open) return(False);
+  if (!Files[fnum1].open) {
+         Files[fnum1].reserved = False;
+         return(False);
+  }
 
   if (!target_is_directory && count)
     ofun = 1;
@@ -3227,6 +3337,7 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
 
   if (!Files[fnum2].open) {
     close_file(fnum1,False);
+    Files[fnum2].reserved = False;
     return(False);
   }
 
@@ -3248,7 +3359,7 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
 /****************************************************************************
   reply to a file copy.
   ****************************************************************************/
-int reply_copy(char *inbuf,char *outbuf)
+int reply_copy(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int outsize = 0;
   pstring name;
@@ -3312,7 +3423,7 @@ int reply_copy(char *inbuf,char *outbuf)
   }
 
   if (is_mangled(mask))
-    check_mangled_stack(mask);
+    check_mangled_cache( mask );
 
   has_wild = strchr(mask,'*') || strchr(mask,'?');
 
@@ -3382,7 +3493,7 @@ int reply_copy(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a setdir
 ****************************************************************************/
-int reply_setdir(char *inbuf,char *outbuf)
+int reply_setdir(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int cnum,snum;
   int outsize = 0;
@@ -3484,7 +3595,14 @@ dev = %x, inode = %x\n",
 
     /* if this is a pure oplock break request then don't send a reply */
     if (num_locks == 0 && num_ulocks == 0)
-           return -1;
+    {
+      /* Sanity check - ensure a pure oplock break is not a
+         chained request. */
+      if(CVAL(inbuf,smb_vwv0) != 0xff)
+        DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
+                 (unsigned int)CVAL(inbuf,smb_vwv0) ));
+      return -1;
+    }
   }
 
   /* Data now points at the beginning of the list
@@ -3604,7 +3722,7 @@ int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize)
 /****************************************************************************
   reply to a SMBwritebmpx (write block multiplex primary) request
 ****************************************************************************/
-int reply_writebmpx(char *inbuf,char *outbuf)
+int reply_writebmpx(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int cnum,numtowrite,fnum;
   int nwritten = -1;
@@ -3697,7 +3815,7 @@ int reply_writebmpx(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a SMBwritebs (write block multiplex secondary) request
 ****************************************************************************/
-int reply_writebs(char *inbuf,char *outbuf)
+int reply_writebs(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int cnum,numtowrite,fnum;
   int nwritten = -1;
@@ -3778,7 +3896,7 @@ int reply_writebs(char *inbuf,char *outbuf)
 /****************************************************************************
   reply to a SMBsetattrE
 ****************************************************************************/
-int reply_setattrE(char *inbuf,char *outbuf)
+int reply_setattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int cnum,fnum;
   struct utimbuf unix_times;
@@ -3831,7 +3949,7 @@ not setting timestamps of 0\n",
 /****************************************************************************
   reply to a SMBgetattrE
 ****************************************************************************/
-int reply_getattrE(char *inbuf,char *outbuf)
+int reply_getattrE(char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int cnum,fnum;
   struct stat sbuf;
@@ -3855,7 +3973,7 @@ int reply_getattrE(char *inbuf,char *outbuf)
   /* Convert the times into dos times. Set create
      date to be last modify date as UNIX doesn't save
      this */
-  put_dos_date2(outbuf,smb_vwv0,sbuf.st_mtime);
+  put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(cnum))));
   put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
   put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
   if (mode & aDIR)