smb-auth-20040711
[openafs.git] / src / WINNT / afsd / smb.c
index c49bb7d..10e69c5 100644 (file)
@@ -28,6 +28,7 @@
 #include <time.h>
 
 #include <osi.h>
+#include <ntstatus.h>
 
 #include "afsd.h"
 
@@ -82,11 +83,16 @@ smb_ncb_t *smb_ncbFreeListp;
 
 int smb_NumServerThreads;
 
-int numNCBs, numSessions;
+int numNCBs, numSessions, numVCs;
 
 int smb_maxVCPerServer;
 int smb_maxMpxRequests;
 
+int smb_authType = SMB_AUTH_EXTENDED; /* type of SMB auth to use. One of SMB_AUTH_* */
+HANDLE smb_lsaHandle;
+ULONG smb_lsaSecPackage;
+LSA_STRING smb_lsaLogonOrigin;
+
 #define NCBmax MAXIMUM_WAIT_OBJECTS
 EVENT_HANDLE NCBavails[NCBmax], NCBevents[NCBmax];
 EVENT_HANDLE **NCBreturns;
@@ -111,6 +117,9 @@ int smb_RawBufSel[SMB_RAW_BUFS];
 char *smb_RawBufs;
 #endif /* DJGPP */
 
+#define SMB_MASKFLAG_TILDE 1
+#define SMB_MASKFLAG_CASEFOLD 2
+
 #define RAWTIMEOUT INFINITE
 
 /* for raw write */
@@ -139,8 +148,10 @@ int smb_hideDotFiles;
 int smb_useV3;         /* try to negotiate V3 */
 
 #ifndef DJGPP
+static showErrors = 1;
 /* MessageBox or something like it */
-int (WINAPI *smb_MBfunc)(HWND, LPCTSTR, LPCTSTR, UINT) = NULL;
+int (_stdcall *smb_MBfunc)(HWND, LPCTSTR, LPCTSTR, UINT) = NULL;
+extern HANDLE WaitToTerminate;
 #endif /* DJGPP */
 
 /* GMT time info:
@@ -182,6 +193,15 @@ extern char cm_confDir[];
 
 extern char AFSConfigKeyName[];
 
+char smb_ServerDomainName[MAX_COMPUTERNAME_LENGTH + 1] = ""; /* domain name */
+int smb_ServerDomainNameLength = 0;
+char smb_ServerOS[] = "Windows 5.0"; /* Faux OS String */
+int smb_ServerOSLength = sizeof(smb_ServerOS);
+char smb_ServerLanManager[] = "Windows 2000 LAN Manager"; /* Faux LAN Manager string */
+int smb_ServerLanManagerLength = sizeof(smb_ServerLanManager);
+
+GUID smb_ServerGUID = { 0x40015cb8, 0x058a, 0x44fc, { 0xae, 0x7e, 0xbb, 0x29, 0x52, 0xee, 0x7e, 0xff }};
+
 /*
  * Demo expiration
  *
@@ -400,7 +420,7 @@ void ShowUnixTime(char *FuncName, long unixTime)
        smb_LargeSearchTimeFromUnixTime(&ft, unixTime);
                 
        if (!FileTimeToDosDateTime(&ft, &wDate, &wTime))
-               osi_Log1(afsd_logp, "Failed to convert filetime to dos datetime: %d", GetLastError());
+               osi_Log1(smb_logp, "Failed to convert filetime to dos datetime: %d", GetLastError());
        else {
                int day, month, year, sec, min, hour;
                char msg[256];
@@ -414,7 +434,7 @@ void ShowUnixTime(char *FuncName, long unixTime)
                hour = ExtractBits(wTime, 11, 5);
 
                sprintf(msg, "%s = %02d-%02d-%04d %02d:%02d:%02d", FuncName, month, day, year, hour, min, sec);
-               osi_Log1(afsd_logp, "%s", osi_LogSaveString(afsd_logp, msg));
+               osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, msg));
        }
 }
 #endif /* DJGPP */
@@ -528,7 +548,14 @@ smb_CalculateNowTZ()
        local_tm = *(localtime(&t));
 
        days = local_tm.tm_yday - gmt_tm.tm_yday;
-       hours = 24 * days + local_tm.tm_hour - gmt_tm.tm_hour - (local_tm.tm_isdst ? 1 : 0);
+       hours = 24 * days + local_tm.tm_hour - gmt_tm.tm_hour
+#ifdef COMMENT
+        /* There is a problem with DST immediately after the time change
+         * which may continue to exist until the machine is rebooted
+         */
+        - (local_tm.tm_isdst ? 1 : 0)
+#endif /* COMMENT */
+        ;
        minutes = 60 * hours + local_tm.tm_min - gmt_tm.tm_min;
        seconds = 60 * minutes + local_tm.tm_sec - gmt_tm.tm_sec;
 
@@ -716,6 +743,7 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
        if (!vcp && (flags & SMB_FLAG_CREATE)) {
                vcp = malloc(sizeof(*vcp));
                memset(vcp, 0, sizeof(*vcp));
+        vcp->vcID = numVCs++;
                vcp->refCount = 1;
                vcp->tidCounter = 1;
                vcp->fidCounter = 1;
@@ -725,6 +753,33 @@ smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
                lock_InitializeMutex(&vcp->mx, "vc_t mutex");
                vcp->lsn = lsn;
                vcp->lana = lana;
+        vcp->secCtx = NULL;
+
+               if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
+            /* We must obtain a challenge for extended auth 
+             * in case the client negotiates smb v3 
+             */
+            NTSTATUS nts,ntsEx;
+                       MSV1_0_LM20_CHALLENGE_REQUEST lsaReq;
+                       PMSV1_0_LM20_CHALLENGE_RESPONSE lsaResp;
+                       ULONG lsaRespSize;
+
+                       lsaReq.MessageType = MsV1_0Lm20ChallengeRequest;
+
+                       nts = LsaCallAuthenticationPackage( smb_lsaHandle,
+                                                smb_lsaSecPackage,
+                                                &lsaReq,
+                                                sizeof(lsaReq),
+                                                &lsaResp,
+                                                &lsaRespSize,
+                                                &ntsEx);
+                       osi_assert(nts == STATUS_SUCCESS); /* this had better work! */
+
+                       memcpy(vcp->encKey, lsaResp->ChallengeToClient, MSV1_0_CHALLENGE_LENGTH);
+            LsaFreeReturnBuffer(lsaResp);
+               }
+               else
+                       memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
        }
        lock_ReleaseWrite(&smb_rctLock);
        return vcp;
@@ -773,6 +828,7 @@ smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
                tidp->nextp = vcp->tidsp;
                tidp->refCount = 1;
                tidp->vcp = vcp;
+        vcp->refCount++;
                vcp->tidsp = tidp;
                lock_InitializeMutex(&tidp->mx, "tid_t mutex");
                tidp->tid = tid;
@@ -786,8 +842,10 @@ void smb_ReleaseTID(smb_tid_t *tidp)
        smb_tid_t *tp;
        smb_tid_t **ltpp;
        cm_user_t *userp;
+    smb_vc_t  *vcp;
 
        userp = NULL;
+    vcp = NULL;
        lock_ObtainWrite(&smb_rctLock);
        osi_assert(tidp->refCount-- > 0);
        if (tidp->refCount == 0 && (tidp->flags & SMB_TIDFLAG_DELETE)) {
@@ -799,11 +857,15 @@ void smb_ReleaseTID(smb_tid_t *tidp)
                *ltpp = tp->nextp;
                lock_FinalizeMutex(&tidp->mx);
                userp = tidp->userp;    /* remember to drop ref later */
+        vcp = tidp->vcp;
        }
        lock_ReleaseWrite(&smb_rctLock);
        if (userp) {
                cm_ReleaseUser(userp);
        }       
+    if (vcp) {
+        smb_ReleaseVC(vcp);
+    }
 }      
 
 smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
@@ -824,8 +886,9 @@ smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
                uidp->nextp = vcp->usersp;
                uidp->refCount = 1;
                uidp->vcp = vcp;
+        vcp->refCount++;
                vcp->usersp = uidp;
-               lock_InitializeMutex(&uidp->mx, "uid_t mutex");
+               lock_InitializeMutex(&uidp->mx, "user_t mutex");
                uidp->userID = uid;
                osi_LogEvent("AFS smb_FindUID (Find by UID)",NULL,"VCP[%x] new-uid[%d] name[%s]",(int)vcp,uidp->userID,(uidp->unp ? uidp->unp->name : ""));
        }
@@ -882,8 +945,10 @@ void smb_ReleaseUID(smb_user_t *uidp)
        smb_user_t *up;
        smb_user_t **lupp;
        cm_user_t *userp;
+    smb_vc_t  *vcp;
 
        userp = NULL;
+    vcp = NULL;
        lock_ObtainWrite(&smb_rctLock);
        osi_assert(uidp->refCount-- > 0);
        if (uidp->refCount == 0 && (uidp->flags & SMB_USERFLAG_DELETE)) {
@@ -898,12 +963,17 @@ void smb_ReleaseUID(smb_user_t *uidp)
                        userp = uidp->unp->userp;       /* remember to drop ref later */
             uidp->unp->userp = NULL;
         }
+        vcp = uidp->vcp;
+        uidp->vcp = NULL;
        }               
        lock_ReleaseWrite(&smb_rctLock);
        if (userp) {
                cm_ReleaseUserVCRef(userp);
                cm_ReleaseUser(userp);
        }       
+    if (vcp) {
+        smb_ReleaseVC(vcp);
+    }
 }      
 
 /* retrieve a held reference to a user structure corresponding to an incoming
@@ -967,19 +1037,24 @@ int smb_SUser(cm_user_t *userp)
        return 1;
 }
 
-/* find a file ID.  If pass in 0, we'll allocate on on a create operation. */
+/* find a file ID.  If we pass in 0 we select an used File ID.
+ * If the SMB_FLAG_CREATE flag is set, we allocate a new  
+ * smb_fid_t data structure if desired File ID cannot be found.
+ */
 smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
 {
        smb_fid_t *fidp;
-       int newFid;
+       int newFid = 0;
         
+    if (fid == 0 && !(flags & SMB_FLAG_CREATE))
+        return NULL;
+
        lock_ObtainWrite(&smb_rctLock);
        /* figure out if we need to allocate a new file ID */
        if (fid == 0) {
                newFid = 1;
                fid = vcp->fidCounter;
        }
-       else newFid = 0;
 
 retry:
        for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
@@ -996,20 +1071,30 @@ retry:
     }
     if (!fidp && (flags & SMB_FLAG_CREATE)) {
         char eventName[MAX_PATH];
-        sprintf(eventName,"fid_t event fid=%d", fid);
+        EVENT_HANDLE event;
+        sprintf(eventName,"fid_t event vcp=%d fid=%d", vcp->vcID, fid);
+        event = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
+        if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
+            afsi_log("Event Object Already Exists: %s", eventName);
+            thrd_CloseHandle(event);
+            fid++;
+            if (fid == 0)
+                fid = 1;
+            goto retry;
+        }
+
                fidp = malloc(sizeof(*fidp));
         memset(fidp, 0, sizeof(*fidp));
                osi_QAdd((osi_queue_t **)&vcp->fidsp, &fidp->q);
         fidp->refCount = 1;
         fidp->vcp = vcp;
+        vcp->refCount++;
         lock_InitializeMutex(&fidp->mx, "fid_t mutex");
         fidp->fid = fid;
                fidp->curr_chunk = fidp->prev_chunk = -2;
-               fidp->raw_write_event = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
-        if ( GetLastError() == ERROR_ALREADY_EXISTS )
-            afsi_log("Event Object Already Exists: %s", eventName);
+               fidp->raw_write_event = event;
         if (newFid) {
-                       vcp->fidCounter = fid+1;
+            vcp->fidCounter = fid+1;
             if (vcp->fidCounter == 0) 
                 vcp->fidCounter = 1;
         }
@@ -1021,7 +1106,7 @@ retry:
 void smb_ReleaseFID(smb_fid_t *fidp)
 {
        cm_scache_t *scp;
-    smb_vc_t *vcp;
+    smb_vc_t *vcp = NULL;
     smb_ioctl_t *ioctlp;
 
     if (!fidp)
@@ -1047,6 +1132,9 @@ void smb_ReleaseFID(smb_fid_t *fidp)
         }
 
         free(fidp);
+
+        /* do not call smb_ReleaseVC() because we already have the lock */
+        vcp->refCount--;
     }
        lock_ReleaseWrite(&smb_rctLock);
 
@@ -1155,13 +1243,12 @@ int smb_ListShares()
 }
 
 /* find a shareName in the table of submounts */
-int smb_FindShare(smb_vc_t *vcp, smb_packet_t *inp, char *shareName,
+int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
        char **pathNamep)
 {
        DWORD len;
        char pathName[1024];
        char *var;
-       smb_user_t *uidp;
        char temp[1024];
        DWORD sizeTemp;
     char sbmtpath[MAX_PATH];
@@ -1229,25 +1316,19 @@ int smb_FindShare(smb_vc_t *vcp, smb_packet_t *inp, char *shareName,
         while (1)
         {
             if (var = smb_stristr(p, VNUserName)) {
-                uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
                 if (uidp && uidp->unp)
                     smb_subst(p, var, sizeof(VNUserName),uidp->unp->name);
                 else
                     smb_subst(p, var, sizeof(VNUserName)," ");
-                if (uidp)
-                    smb_ReleaseUID(uidp);
             }
             else if (var = smb_stristr(p, VNLCUserName)) 
             {
-                uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
                 if (uidp && uidp->unp)
                     strcpy(temp, uidp->unp->name);
                 else 
                     strcpy(temp, " ");
                 _strlwr(temp);
                 smb_subst(p, var, sizeof(VNLCUserName), temp);
-                if (uidp)
-                    smb_ReleaseUID(uidp);
             }
             else if (var = smb_stristr(p, VNComputerName)) 
             {
@@ -1297,6 +1378,48 @@ int smb_FindShare(smb_vc_t *vcp, smb_packet_t *inp, char *shareName,
     return 0;
 }
 
+/* Client-side offline caching policy types */
+#define CSC_POLICY_MANUAL 0
+#define CSC_POLICY_DOCUMENTS 1
+#define CSC_POLICY_PROGRAMS 2
+#define CSC_POLICY_DISABLE 3
+
+int smb_FindShareCSCPolicy(char *shareName)
+{
+       DWORD len;
+       char policy[1024];
+       char sbmtpath[256];
+
+#ifndef DJGPP
+        strcpy(sbmtpath, "afsdsbmt.ini");
+#else /* DJGPP */
+        strcpy(sbmtpath, cm_confDir);
+        strcat(sbmtpath, "/afsdsbmt.ini");
+#endif /* !DJGPP */
+       len = GetPrivateProfileString("CSC Policy", shareName, "",
+                                     policy, sizeof(policy), sbmtpath);
+       if (len == 0 || len == sizeof(policy) - 1) {
+               return CSC_POLICY_MANUAL;
+       }
+       
+       if (stricmp(policy, "documents") == 0)
+       {
+               return CSC_POLICY_DOCUMENTS;
+       }
+       
+       if (stricmp(policy, "programs") == 0)
+       {
+               return CSC_POLICY_PROGRAMS;
+       }
+       
+       if (stricmp(policy, "disable") == 0)
+       {
+               return CSC_POLICY_DISABLE;
+       }
+       
+       return CSC_POLICY_MANUAL;
+}
+
 /* find a dir search structure by cookie value, and return it held.
  * Must be called with smb_globalLock held.
  */
@@ -1674,7 +1797,7 @@ unsigned int smb_GetSMBParm(smb_packet_t *smbp, int parm)
 
                sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
                                parm, parmCount, smbp->ncb_length);
-               osi_Log0(afsd_logp, s);
+               osi_Log0(smb_logp, s);
 #endif /* !DJGPP */
                osi_panic(s, __FILE__, __LINE__);
        }
@@ -1709,7 +1832,7 @@ unsigned int smb_GetSMBOffsetParm(smb_packet_t *smbp, int parm, int offset)
                sprintf(s, "Bad SMB param %d offset %d out of %d, "
                                "ncb len %d",
                                 parm, offset, parmCount, smbp->ncb_length);
-               osi_Log0(afsd_logp, s);
+               osi_Log0(smb_logp, s);
 #endif /* !DJGPP */
 
                osi_panic(s, __FILE__, __LINE__);
@@ -1907,7 +2030,7 @@ void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp)
 #endif /* !DJGPP */
         
        if (code != 0)
-               osi_Log1(afsd_logp, "SendPacket failure code %d", code);
+               osi_Log1(smb_logp, "SendPacket failure code %d", code);
 
        if (localNCB)
                FreeNCB(ncbp);
@@ -1918,6 +2041,7 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
        unsigned long NTStatus;
 
        /* map CM_ERROR_* errors to NT 32-bit status codes */
+    /* NT Status codes are listed in ntstatus.h not winerror.h */
        if (code == CM_ERROR_NOSUCHCELL) {
                NTStatus = 0xC000000FL; /* No such file */
        }
@@ -2012,12 +2136,24 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
        else if (code == CM_ERROR_BUFFERTOOSMALL) {
                NTStatus = 0xC0000023L; /* Buffer too small */
        }
+    else if (code == CM_ERROR_AMBIGUOUS_FILENAME) {
+               NTStatus = 0xC0000035L; /* Object name collision */
+    }
+       else if (code == CM_ERROR_BADPASSWORD) {
+               NTStatus = 0xC000006DL; /* unknown username or bad password */
+       }
+       else if (code == CM_ERROR_BADLOGONTYPE) {
+               NTStatus = 0xC000015BL; /* logon type not granted */
+       }
+       else if (code == CM_ERROR_GSSCONTINUE) {
+               NTStatus = 0xC0000016L; /* more processing required */
+       }
        else {
                NTStatus = 0xC0982001L; /* SMB non-specific error */
        }
 
        *NTStatusp = NTStatus;
-       osi_Log2(afsd_logp, "SMB SEND code %x as NT %x", code, NTStatus);
+       osi_Log2(smb_logp, "SMB SEND code %x as NT %x", code, NTStatus);
 }
 
 void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep,
@@ -2163,6 +2299,11 @@ void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep,
                class = 1;
                error = 183;     /* Samba uses this */
        }
+       else if (code == CM_ERROR_BADPASSWORD || code == CM_ERROR_BADLOGONTYPE) {
+               /* we don't have a good way of reporting CM_ERROR_BADLOGONTYPE */
+               class = 2;
+               error = 2; /* bad password */
+       }
        else {
                class = 2;
                error = 1;
@@ -2170,7 +2311,7 @@ void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep,
 
        *scodep = error;
        *classp = class;
-       osi_Log3(afsd_logp, "SMB SEND code %x as SMB %d: %d", code, class, error);
+       osi_Log3(smb_logp, "SMB SEND code %x as SMB %d: %d", code, class, error);
 }
 
 long smb_SendCoreBadOp(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
@@ -2224,7 +2365,7 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
        offset.HighPart = 0;    /* too bad */
        offset.LowPart = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
 
-       osi_Log3(afsd_logp, "smb_ReceieveCoreReadRaw fd %d, off 0x%x, size 0x%x",
+       osi_Log3(smb_logp, "smb_ReceieveCoreReadRaw fd %d, off 0x%x, size 0x%x",
              fd, offset.LowPart, count);
 
        fidp = smb_FindFID(vcp, fd, 0);
@@ -2307,7 +2448,7 @@ long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
        code = Netbios(ncbp, dos_ncb);
 #endif /* !DJGPP */
        if (code != 0)
-               osi_Log1(afsd_logp, "ReadRaw send failure code %d", code);
+               osi_Log1(smb_logp, "ReadRaw send failure code %d", code);
 
        if (rawBuf) {
                /* Give back raw buffer */
@@ -2338,26 +2479,36 @@ long smb_ReceiveCoreUnlockRecord(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t
 long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
        char *namep;
+    char *datap;
        int coreProtoIndex;
        int v3ProtoIndex;
        int NTProtoIndex;
-       int protoIndex;                 /* index we're using */
+       int protoIndex;                         /* index we're using */
        int namex;
        int dbytes;
        int entryLength;
        int tcounter;
-       char protocol_array[10][1024]; /* protocol signature of the client */
+       char protocol_array[10][1024];  /* protocol signature of the client */
+    int caps;                       /* capabilities */
+    time_t unixTime;
+       long dosTime;
+       TIME_ZONE_INFORMATION tzi;
 
-        
-       osi_Log1(afsd_logp, "SMB receive negotiate; %d + 1 ongoing ops",
+    osi_Log1(smb_logp, "SMB receive negotiate; %d + 1 ongoing ops",
                         ongoingOps - 1);
        if (!isGateway) {
                if (active_vcp) {
                        DWORD now = GetCurrentTime();
                        if (now - last_msg_time >= 30000
                                && now - last_msg_time <= 90000) {
-                               osi_Log1(afsd_logp,
+                               osi_Log1(smb_logp,
                                                 "Setting dead_vcp %x", active_vcp);
+                if (dead_vcp) {
+                    smb_ReleaseVC(dead_vcp);
+                    osi_Log1(smb_logp,
+                              "Previous dead_vcp %x", dead_vcp);
+                }
+                smb_HoldVC(active_vcp);
                                dead_vcp = active_vcp;
                                dead_vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
                        }
@@ -2373,8 +2524,8 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        v3ProtoIndex = -1;
        NTProtoIndex = -1;
        while(namex < dbytes) {
-               osi_Log1(afsd_logp, "Protocol %s",
-                                osi_LogSaveString(afsd_logp, namep+1));
+               osi_Log1(smb_logp, "Protocol %s",
+                                osi_LogSaveString(smb_logp, namep+1));
                strcpy(protocol_array[tcounter], namep+1);
 
                /* namep points at the first protocol, or really, a 0x02
@@ -2420,7 +2571,7 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                         (strcmp("LANMAN2.1", protocol_array[4]) == 0) &&
                         (strcmp("NT LM 0.12", protocol_array[5]) == 0)) {
                        isWindows2000 = TRUE;
-                       osi_Log0(afsd_logp, "Looks like a Windows 2000 client");
+                       osi_Log0(smb_logp, "Looks like a Windows 2000 client");
                        /* 
                         * HACK: for now - just negotiate a lower protocol till we 
                         * figure out which flag/flag2 or some other field 
@@ -2431,7 +2582,7 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                        /* Things to try (after looking at tcpdump output could be
                         * setting flags and flags2 to 0x98 and 0xc853 like this
                         * op->reb = 0x98; op->flg2 = 0xc853;
-                        * osi_Log2(afsd_logp, "Flags:0x%x Flags2:0x%x", ip->reb, ip->flg2);
+                        * osi_Log2(smb_logp, "Flags:0x%x Flags2:0x%x", ip->reb, ip->flg2);
                         */
                }       
        }       
@@ -2454,12 +2605,23 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        if (protoIndex == -1)
                return CM_ERROR_INVAL;
        else if (NTProtoIndex != -1) {
-               smb_SetSMBParm(outp, 0, protoIndex);
-        smb_SetSMBParmByte(outp, 1, 0);        /* share level security, no passwd encrypt */
+        smb_SetSMBParm(outp, 0, protoIndex);
+               if (smb_authType != SMB_AUTH_NONE) {
+                       smb_SetSMBParmByte(outp, 1,
+                               NEGOTIATE_SECURITY_USER_LEVEL |
+                               NEGOTIATE_SECURITY_CHALLENGE_RESPONSE); /* user level security, challenge response */
+               } else {
+            smb_SetSMBParmByte(outp, 1, 0); /* share level auth with plaintext password. */
+               }
         smb_SetSMBParm(outp, 1, smb_maxMpxRequests);   /* max multiplexed requests */
         smb_SetSMBParm(outp, 2, smb_maxVCPerServer);   /* max VCs per consumer/server connection */
-        smb_SetSMBParmLong(outp, 3, SMB_PACKETSIZE); /* xmit buffer size */
-               smb_SetSMBParmLong(outp, 5, 65536);     /* raw buffer size */
+        smb_SetSMBParmLong(outp, 3, SMB_PACKETSIZE);    /* xmit buffer size */
+               smb_SetSMBParmLong(outp, 5, SMB_MAXRAWSIZE);    /* raw buffer size */
+        /* The session key is not a well documented field however most clients
+         * will echo back the session key to the server.  Currently we are using
+         * the same value for all sessions.  We should generate a random value
+         * and store it into the vcp 
+         */
         smb_SetSMBParm(outp, 7, 1);    /* next 2: session key */
         smb_SetSMBParm(outp, 8, 1);
                /* 
@@ -2477,30 +2639,100 @@ long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                 * and NT Find *
                 * and NT SMB's *
                 * and raw mode */
-               smb_SetSMBParmLong(outp, 9, 0x251);     
-               smb_SetSMBParmLong(outp, 11, 0);/* XXX server time: do we need? */
-               smb_SetSMBParmLong(outp, 13, 0);/* XXX server date: do we need? */
-               smb_SetSMBParm(outp, 15, 0);    /* XXX server tzone: do we need? */
-               smb_SetSMBParmByte(outp, 16, 0);/* Encryption key length */
-               smb_SetSMBDataLength(outp, 0);  /* perhaps should specify 8 bytes anyway */
+        caps = NTNEGOTIATE_CAPABILITY_NTSTATUS |
+                          NTNEGOTIATE_CAPABILITY_NTFIND |
+               NTNEGOTIATE_CAPABILITY_RAWMODE |
+                          NTNEGOTIATE_CAPABILITY_NTSMB;
+
+        if ( smb_authType == SMB_AUTH_EXTENDED )
+            caps |= NTNEGOTIATE_CAPABILITY_EXTENDED_SECURITY;
+
+        smb_SetSMBParmLong(outp, 9, caps);
+               time(&unixTime);
+               smb_SearchTimeFromUnixTime(&dosTime, unixTime);
+               smb_SetSMBParmLong(outp, 11, LOWORD(dosTime));/* server time */
+               smb_SetSMBParmLong(outp, 13, HIWORD(dosTime));/* server date */
+
+               GetTimeZoneInformation(&tzi);
+               smb_SetSMBParm(outp, 15, (unsigned short) tzi.Bias);    /* server tzone */
+
+               if (smb_authType == SMB_AUTH_NTLM) {
+                       smb_SetSMBParmByte(outp, 16, MSV1_0_CHALLENGE_LENGTH);/* Encryption key length */
+                       smb_SetSMBDataLength(outp, MSV1_0_CHALLENGE_LENGTH + smb_ServerDomainNameLength);
+                       /* paste in encryption key */
+                       datap = smb_GetSMBData(outp, NULL);
+                       memcpy(datap,vcp->encKey,MSV1_0_CHALLENGE_LENGTH);
+                       /* and the faux domain name */
+                       strcpy(datap + MSV1_0_CHALLENGE_LENGTH,smb_ServerDomainName);
+               } else if ( smb_authType == SMB_AUTH_EXTENDED ) {
+            void * secBlob;
+                       int secBlobLength;
+
+                       smb_SetSMBParmByte(outp, 16, 0); /* Encryption key length */
+
+                       smb_NegotiateExtendedSecurity(&secBlob, &secBlobLength);
+
+                       smb_SetSMBDataLength(outp, secBlobLength + sizeof(smb_ServerGUID));
+                       
+                       datap = smb_GetSMBData(outp, NULL);
+                       memcpy(datap, &smb_ServerGUID, sizeof(smb_ServerGUID));
+
+                       if (secBlob) {
+                               datap += sizeof(smb_ServerGUID);
+                               memcpy(datap, secBlob, secBlobLength);
+                               free(secBlob);
+                       }
+        } else {
+                       smb_SetSMBParmByte(outp, 16, 0); /* Encryption key length */
+                       smb_SetSMBDataLength(outp, 0);   /* Perhaps we should specify 8 bytes anyway */
+               }
        }
        else if (v3ProtoIndex != -1) {
                smb_SetSMBParm(outp, 0, protoIndex);
-               smb_SetSMBParm(outp, 1, 0);     /* share level security, no passwd encrypt */
+
+        /* NOTE: Extended authentication cannot be negotiated with v3
+         * therefore we fail over to NTLM 
+         */
+        if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
+                       smb_SetSMBParm(outp, 1,
+                               NEGOTIATE_SECURITY_USER_LEVEL |
+                               NEGOTIATE_SECURITY_CHALLENGE_RESPONSE); /* user level security, challenge response */
+               } else {
+                       smb_SetSMBParm(outp, 1, 0); /* share level auth with clear password */
+               }
                smb_SetSMBParm(outp, 2, SMB_PACKETSIZE);
                smb_SetSMBParm(outp, 3, smb_maxMpxRequests);    /* max multiplexed requests */
                smb_SetSMBParm(outp, 4, smb_maxVCPerServer);    /* max VCs per consumer/server connection */
                smb_SetSMBParm(outp, 5, 0);     /* no support of block mode for read or write */
                smb_SetSMBParm(outp, 6, 1);     /* next 2: session key */
                smb_SetSMBParm(outp, 7, 1);
-               smb_SetSMBParm(outp, 8, 0);     /* XXX server time: do we need? */
-               smb_SetSMBParm(outp, 9, 0);     /* XXX server date: do we need? */
-               smb_SetSMBParm(outp, 10, 0);    /* XXX server tzone: do we need? */
-               smb_SetSMBParm(outp, 11, 0);    /* resvd */
-               smb_SetSMBParm(outp, 12, 0);    /* resvd */
-               smb_SetSMBDataLength(outp, 0);  /* perhaps should specify 8 bytes anyway */
+               time(&unixTime);
+               smb_SearchTimeFromUnixTime(&dosTime, unixTime);
+               smb_SetSMBParm(outp, 8, LOWORD(dosTime));       /* server time */
+               smb_SetSMBParm(outp, 9, HIWORD(dosTime));       /* server date */
+
+               GetTimeZoneInformation(&tzi);
+               smb_SetSMBParm(outp, 10, (unsigned short) tzi.Bias);    /* server tzone */
+
+        /* NOTE: Extended authentication cannot be negotiated with v3
+         * therefore we fail over to NTLM 
+         */
+               if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
+                       smb_SetSMBParm(outp, 11, MSV1_0_CHALLENGE_LENGTH);      /* encryption key length */
+            smb_SetSMBParm(outp, 12, 0);       /* resvd */
+                       smb_SetSMBDataLength(outp, MSV1_0_CHALLENGE_LENGTH + smb_ServerDomainNameLength);       /* perhaps should specify 8 bytes anyway */
+                       datap = smb_GetSMBData(outp, NULL);
+                       /* paste in a new encryption key */
+                       memcpy(datap, vcp->encKey, MSV1_0_CHALLENGE_LENGTH);
+                       /* and the faux domain name */
+                       strcpy(datap + MSV1_0_CHALLENGE_LENGTH, smb_ServerDomainName);
+               } else {
+                       smb_SetSMBParm(outp, 11, 0); /* encryption key length */
+                       smb_SetSMBParm(outp, 12, 0); /* resvd */
+                       smb_SetSMBDataLength(outp, 0);
+               }
        }
-       else if (coreProtoIndex != -1) {
+       else if (coreProtoIndex != -1) {     /* not really supported anymore */
                smb_SetSMBParm(outp, 0, protoIndex);
                smb_SetSMBDataLength(outp, 0);
        }
@@ -2514,8 +2746,21 @@ void smb_Daemon(void *parmp)
        while(1) {
                count++;
                thrd_Sleep(10000);
-               if ((count % 360) == 0)         /* every hour */
-                       smb_CalculateNowTZ();
+               if ((count % 360) == 0) {       /* every hour */
+            struct tm myTime;
+                
+            /* Initialize smb_localZero */
+            myTime.tm_isdst = -1;              /* compute whether on DST or not */
+            myTime.tm_year = 70;
+            myTime.tm_mon = 0;
+            myTime.tm_mday = 1;
+            myTime.tm_hour = 0;
+            myTime.tm_min = 0;
+            myTime.tm_sec = 0;
+            smb_localZero = mktime(&myTime);
+
+            smb_CalculateNowTZ();
+        }
                /* XXX GC dir search entries */
        }
 }
@@ -2590,7 +2835,7 @@ void smb_WaitingLocksDaemon()
 
 long smb_ReceiveCoreGetDiskAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-       osi_Log0(afsd_logp, "SMB receive get disk attributes");
+       osi_Log0(smb_logp, "SMB receive get disk attributes");
 
        smb_SetSMBParm(outp, 0, 32000);
        smb_SetSMBParm(outp, 1, 64);
@@ -2604,6 +2849,7 @@ long smb_ReceiveCoreGetDiskAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
 long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *rsp)
 {
        smb_tid_t *tidp;
+    smb_user_t *uidp;
        unsigned short newTid;
        char shareName[256];
        char *sharePath;
@@ -2613,7 +2859,7 @@ long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
        char *passwordp;
        cm_user_t *userp;
 
-       osi_Log0(afsd_logp, "SMB receive tree connect");
+       osi_Log0(smb_logp, "SMB receive tree connect");
 
        /* parse input parameters */
        tp = smb_GetSMBData(inp, NULL);
@@ -2631,7 +2877,10 @@ long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
        lock_ReleaseMutex(&vcp->mx);
         
        tidp = smb_FindTID(vcp, newTid, SMB_FLAG_CREATE);
-       shareFound = smb_FindShare(vcp, inp, shareName, &sharePath);
+    uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
+       shareFound = smb_FindShare(vcp, uidp, shareName, &sharePath);
+    if (uidp)
+        smb_ReleaseUID(uidp);
        if (!shareFound) {
                smb_ReleaseTID(tidp);
                return CM_ERROR_BADSHARENAME;
@@ -2646,7 +2895,7 @@ long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *
        smb_SetSMBParm(rsp, 1, newTid);
        smb_SetSMBDataLength(rsp, 0);
 
-       osi_Log1(afsd_logp, "SMB tree connect created ID %d", newTid);
+       osi_Log1(smb_logp, "SMB tree connect created ID %d", newTid);
        return 0;
 }
 
@@ -2785,7 +3034,7 @@ long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t
        unsigned char initStatBlock[21];
        int statLen;
         
-       osi_Log0(afsd_logp, "SMB receive search volume");
+       osi_Log0(smb_logp, "SMB receive search volume");
 
        /* pull pathname and stat block out of request */
        tp = smb_GetSMBData(inp, NULL);
@@ -2986,8 +3235,8 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                if (attribute & 0x8)
                        return smb_ReceiveCoreSearchVolume(vcp, inp, outp);
 
-               osi_Log2(afsd_logp, "SMB receive search dir count %d [%s]",
-                                maxCount, osi_LogSaveString(afsd_logp, pathp));
+               osi_Log2(smb_logp, "SMB receive search dir count %d [%s]",
+                                maxCount, osi_LogSaveString(smb_logp, pathp));
 
                if (*pathp == 0) {      /* null pathp, treat as root dir */
                        if (!(attribute & SMB_ATTR_DIRECTORY))  /* exclude dirs */
@@ -3029,7 +3278,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                starPattern = 1;
        }
 
-       osi_Log3(afsd_logp, "SMB dir search cookie 0x%x, connection %d, attr 0x%x",
+       osi_Log3(smb_logp, "SMB dir search cookie 0x%x, connection %d, attr 0x%x",
                         nextCookie, dsp->cookie, attribute);
 
        userp = smb_GetUser(vcp, inp);
@@ -3269,7 +3518,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
                                fid.vnode = ntohl(dep->fid.vnode);
                                fid.unique = ntohl(dep->fid.unique);
                                fileType = cm_FindFileType(&fid);
-                               osi_Log2(afsd_logp, "smb_ReceiveCoreSearchDir: file %s "
+                               osi_Log2(smb_logp, "smb_ReceiveCoreSearchDir: file %s "
                                                  "has filetype %d", dep->name,
                                                  fileType);
                                if (fileType == CM_SCACHETYPE_DIRECTORY)
@@ -3358,7 +3607,7 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
        if (code == 0 && dataLength < 21 && returnedNames == 0)
                code = CM_ERROR_NOFILES;
 
-       osi_Log2(afsd_logp, "SMB search dir done, %d names, code %d",
+       osi_Log2(smb_logp, "SMB search dir done, %d names, code %d",
                 returnedNames, code);
 
        if (code != 0) {
@@ -3409,8 +3658,8 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
 
        pathp = smb_GetSMBData(inp, NULL);
        pathp = smb_ParseASCIIBlock(pathp, NULL);
-       osi_Log1(afsd_logp, "SMB receive check path %s",
-                         osi_LogSaveString(afsd_logp, pathp));
+       osi_Log1(smb_logp, "SMB receive check path %s",
+                         osi_LogSaveString(smb_logp, pathp));
 
        if (!pathp) {
                return CM_ERROR_BADFD;
@@ -3482,7 +3731,7 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
                return CM_ERROR_BADSMB;
        }
         
-       osi_Log2(afsd_logp, "SMB receive setfile attributes time %d, attr 0x%x",
+       osi_Log2(smb_logp, "SMB receive setfile attributes time %d, attr 0x%x",
                         dosTime, attribute);
 
        rootScp = cm_rootSCachep;
@@ -3579,8 +3828,8 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack
        if (*pathp == 0)                /* null path */
                pathp = "\\";
 
-       osi_Log1(afsd_logp, "SMB receive getfile attributes path %s",
-                        osi_LogSaveString(afsd_logp, pathp));
+       osi_Log1(smb_logp, "SMB receive getfile attributes path %s",
+                        osi_LogSaveString(smb_logp, pathp));
 
        rootScp = cm_rootSCachep;
         
@@ -3692,7 +3941,7 @@ long smb_ReceiveCoreTreeDisconnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_
 {
        smb_tid_t *tidp;
         
-       osi_Log0(afsd_logp, "SMB receive tree disconnect");
+       osi_Log0(smb_logp, "SMB receive tree disconnect");
 
        /* find the tree and free it */
        tidp = smb_FindTID(vcp, ((smb_t *)inp)->tid, 0);
@@ -3727,7 +3976,7 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     pathp = smb_GetSMBData(inp, NULL);
     pathp = smb_ParseASCIIBlock(pathp, NULL);
        
-    osi_Log1(afsd_logp, "SMB receive open file [%s]", osi_LogSaveString(afsd_logp, pathp));
+    osi_Log1(smb_logp, "SMB receive open file [%s]", osi_LogSaveString(smb_logp, pathp));
 
 #ifdef DEBUG_VERBOSE
     {
@@ -3835,7 +4084,7 @@ typedef struct smb_unlinkRock {
        cm_req_t *reqp;
        smb_vc_t *vcp;
        char *maskp;            /* pointer to the star pattern */
-       int hasTilde;
+       int flags;
        int any;
 } smb_unlinkRock_t;
 
@@ -3850,19 +4099,19 @@ int smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
         
        rockp = vrockp;
 
-       if (rockp->vcp->flags & SMB_VCFLAG_USEV3)
-               caseFold = CM_FLAG_CASEFOLD;
-       else 
-               caseFold = CM_FLAG_CASEFOLD | CM_FLAG_8DOT3;
+    caseFold = ((rockp->flags & SMB_MASKFLAG_CASEFOLD)? CM_FLAG_CASEFOLD : 0);
+    if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
+        caseFold |= CM_FLAG_8DOT3;
 
        matchName = dep->name;
        match = smb_V3MatchMask(matchName, rockp->maskp, caseFold);
        if (!match
-           && rockp->hasTilde
+           && (rockp->flags & SMB_MASKFLAG_TILDE)
            && !cm_Is8Dot3(dep->name)) {
                cm_Gen8Dot3Name(dep, shortName, NULL);
                matchName = shortName;
-               match = smb_V3MatchMask(matchName, rockp->maskp, caseFold);
+        /* 8.3 matches are always case insensitive */
+        match = smb_V3MatchMask(matchName, rockp->maskp, caseFold | CM_FLAG_CASEFOLD);
        }
        if (match) {
                osi_Log1(smb_logp, "Unlinking %s",
@@ -3872,8 +4121,12 @@ int smb_UnlinkProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
                        smb_NotifyChange(FILE_ACTION_REMOVED,
                                                         FILE_NOTIFY_CHANGE_FILE_NAME,
                                                         dscp, dep->name, NULL, TRUE);
-               if (code == 0)
+               if (code == 0) {
                        rockp->any = 1;
+            /* If we made a case sensitive exact match, we might as well quit now. */
+            if(!(rockp->flags & SMB_MASKFLAG_CASEFOLD) && !strcmp(matchName, rockp->maskp))
+                code = CM_ERROR_STOPNOW;
+        }
        }
        else code = 0;
 
@@ -3930,7 +4183,7 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        rock.any = 0;
        rock.maskp = smb_FindMask(pathp);
-       rock.hasTilde = ((strchr(rock.maskp, '~') != NULL) ? 1 : 0);
+       rock.flags = ((strchr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
         
        thyper.LowPart = 0;
        thyper.HighPart = 0;
@@ -3938,7 +4191,25 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        rock.reqp = &req;
        rock.dscp = dscp;
        rock.vcp = vcp;
-       code = cm_ApplyDir(dscp, smb_UnlinkProc, &rock, &thyper, userp, &req, NULL);
+
+    /* Now, if we aren't dealing with a wildcard match, we first try an exact 
+     * match.  If that fails, we do a case insensitve match. 
+     */
+    if (!(rock.flags & SMB_MASKFLAG_TILDE) &&
+        !smb_IsStarMask(rock.maskp)) {
+        code = cm_ApplyDir(dscp, smb_UnlinkProc, &rock, &thyper, userp, &req, NULL);
+        if(!rock.any) {
+            thyper.LowPart = 0;
+            thyper.HighPart = 0;
+            rock.flags |= SMB_MASKFLAG_CASEFOLD;
+        }
+    }
+    if (!rock.any)
+        code = cm_ApplyDir(dscp, smb_UnlinkProc, &rock, &thyper, userp, &req, NULL);
+    
+    if (code == CM_ERROR_STOPNOW) 
+        code = 0;
 
        cm_ReleaseUser(userp);
         
@@ -3956,7 +4227,7 @@ typedef struct smb_renameRock {
        cm_req_t *reqp;         /* request struct */
        smb_vc_t *vcp;          /* virtual circuit */
        char *maskp;            /* pointer to star pattern of old file name */
-       int hasTilde;           /* star pattern might be shortname? */
+       int flags;                  /* tilde, casefold, etc */
        char *newNamep;         /* ptr to the new file's name */
 } smb_renameRock_t;
 
@@ -3968,16 +4239,15 @@ int smb_RenameProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype
        int match;
        char shortName[13];
         
-       rockp = vrockp;
+       rockp = (smb_renameRock_t *) vrockp;
 
-       if (rockp->vcp->flags & SMB_VCFLAG_USEV3)
-               caseFold = CM_FLAG_CASEFOLD;
-       else 
-               caseFold = CM_FLAG_CASEFOLD | CM_FLAG_8DOT3;
+    caseFold = ((rockp->flags & SMB_MASKFLAG_CASEFOLD)? CM_FLAG_CASEFOLD : 0);
+    if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
+        caseFold |= CM_FLAG_8DOT3;
 
        match = smb_V3MatchMask(dep->name, rockp->maskp, caseFold);
        if (!match
-           && rockp->hasTilde
+           && (rockp->flags & SMB_MASKFLAG_TILDE)
            && !cm_Is8Dot3(dep->name)) {
                cm_Gen8Dot3Name(dep, shortName, NULL);
                match = smb_V3MatchMask(shortName, rockp->maskp, caseFold);
@@ -4003,11 +4273,12 @@ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        char *oldPathp;
        char *newPathp;
        char *tp;
-       cm_space_t *spacep;
+       cm_space_t *spacep = NULL;
        smb_renameRock_t rock;
-       cm_scache_t *oldDscp;
-       cm_scache_t *newDscp;
-       cm_scache_t *tmpscp;
+       cm_scache_t *oldDscp = NULL;
+       cm_scache_t *newDscp = NULL;
+       cm_scache_t *tmpscp= NULL;
+       cm_scache_t *tmpscp2 = NULL;
        char *oldLastNamep;
        char *newLastNamep;
        osi_hyper_t thyper;
@@ -4023,9 +4294,9 @@ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        oldPathp = smb_ParseASCIIBlock(tp, &tp);
        newPathp = smb_ParseASCIIBlock(tp, &tp);
 
-       osi_Log2(afsd_logp, "smb rename %s to %s",
-                        osi_LogSaveString(afsd_logp, oldPathp),
-                        osi_LogSaveString(afsd_logp, newPathp));
+       osi_Log2(smb_logp, "smb rename [%s] to [%s]",
+                        osi_LogSaveString(smb_logp, oldPathp),
+                        osi_LogSaveString(smb_logp, newPathp));
 
        spacep = inp->spacep;
        smb_StripLastComponent(spacep->data, &oldLastNamep, oldPathp);
@@ -4079,6 +4350,8 @@ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                newLastNamep = newPathp;
        else 
                newLastNamep++;
+
+    /* TODO: The old name could be a wildcard.  The new name must not be */
        
        /* do the vnode call */
        rock.odscp = oldDscp;
@@ -4087,16 +4360,44 @@ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        rock.reqp = &req;
        rock.vcp = vcp;
        rock.maskp = oldLastNamep;
-       rock.hasTilde = ((strchr(oldLastNamep, '~') != NULL) ? 1 : 0);
+       rock.flags = ((strchr(oldLastNamep, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
        rock.newNamep = newLastNamep;
 
     /* Check if the file already exists; if so return error */
        code = cm_Lookup(newDscp,newLastNamep,CM_FLAG_CHECKPATH,userp,&req,&tmpscp);
-       if((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_NOSUCHPATH) && (code != CM_ERROR_NOSUCHVOLUME) ) {
-           cm_ReleaseSCache(tmpscp);
-           return CM_ERROR_EXISTS; /* file exist, do not rename, also 
-                                        * fixes move
-                                                                */
+       if ((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_NOSUCHPATH) && (code != CM_ERROR_NOSUCHVOLUME) ) {
+        osi_Log2(afsd_logp, "  lookup returns %ld for [%s]", code,
+                 osi_LogSaveString(afsd_logp, newLastNamep));
+        /* Check if the old and the new names differ only in case. If so return
+         * success, else return CM_ERROR_EXISTS 
+         */
+        if (!code && oldDscp == newDscp && !stricmp(oldLastNamep, newLastNamep)) {
+
+            /* This would be a success only if the old file is *as same as* the new file */
+            code = cm_Lookup(oldDscp, oldLastNamep, CM_FLAG_CHECKPATH, userp, &req, &tmpscp2);
+            if (!code) {
+                if (tmpscp == tmpscp2) 
+                    code = 0;
+                else 
+                    code = CM_ERROR_EXISTS;
+                cm_ReleaseSCache(tmpscp2);
+                               tmpscp2 = NULL;
+            } else {
+                code = CM_ERROR_NOSUCHFILE;
+            }
+        } else {
+            /* file exist, do not rename, also fixes move */
+            osi_Log0(afsd_logp, "Can't rename.  Target already exists");
+            code = CM_ERROR_EXISTS;
+        }
+
+               if(tmpscp != NULL)
+            cm_ReleaseSCache(tmpscp);
+        cm_ReleaseSCache(newDscp);
+        cm_ReleaseSCache(oldDscp);
+        cm_ReleaseUser(userp);
+           return code; 
        }
 
     /* Now search the directory for the pattern, and do the appropriate rename when found */
@@ -4132,11 +4433,11 @@ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                                                         NULL, TRUE);
        }
 
-       cm_ReleaseUser(userp);
-        
+    if(tmpscp != NULL) 
+        cm_ReleaseSCache(tmpscp);
+    cm_ReleaseUser(userp);
        cm_ReleaseSCache(oldDscp);
        cm_ReleaseSCache(newDscp);
-
        return code;
 }
 
@@ -4145,7 +4446,7 @@ typedef struct smb_rmdirRock {
        cm_user_t *userp;
        cm_req_t *reqp;
        char *maskp;            /* pointer to the star pattern */
-       int hasTilde;
+       int flags;
        int any;
 } smb_rmdirRock_t;
 
@@ -4157,12 +4458,15 @@ int smb_RmdirProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hyper
        char shortName[13];
        char *matchName;
         
-       rockp = vrockp;
+       rockp = (smb_rmdirRock_t *) vrockp;
 
        matchName = dep->name;
-       match = (cm_stricmp(matchName, rockp->maskp) == 0);
+    if (rockp->flags & SMB_MASKFLAG_CASEFOLD)
+        match = (cm_stricmp(matchName, rockp->maskp) == 0);
+    else
+        match = (strcmp(matchName, rockp->maskp) == 0);
        if (!match
-           && rockp->hasTilde
+           && (rockp->flags & SMB_MASKFLAG_TILDE)
            && !cm_Is8Dot3(dep->name)) {
                cm_Gen8Dot3Name(dep, shortName, NULL);
                matchName = shortName;
@@ -4228,14 +4532,21 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
        
        rock.any = 0;
        rock.maskp = lastNamep;
-       rock.hasTilde = ((strchr(rock.maskp, '~') != NULL) ? 1 : 0);
+       rock.flags = ((strchr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
 
        thyper.LowPart = 0;
        thyper.HighPart = 0;
        rock.userp = userp;
        rock.reqp = &req;
        rock.dscp = dscp;
-       code = cm_ApplyDir(dscp, smb_RmdirProc, &rock, &thyper, userp, &req, NULL);
+    /* First do a case sensitive match, and if that fails, do a case insensitive match */
+    code = cm_ApplyDir(dscp, smb_RmdirProc, &rock, &thyper, userp, &req, NULL);
+    if (code == 0 && !rock.any) {
+        thyper.LowPart = 0;
+        thyper.HighPart = 0;
+        rock.flags |= SMB_MASKFLAG_CASEFOLD;
+        code = cm_ApplyDir(dscp, smb_RmdirProc, &rock, &thyper, userp, &req, NULL);
+    }
 
        cm_ReleaseUser(userp);
         
@@ -4258,7 +4569,7 @@ long smb_ReceiveCoreFlush(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        fid = smb_GetSMBParm(inp, 0);
         
-       osi_Log1(afsd_logp, "SMB flush fid %d", fid);
+       osi_Log1(smb_logp, "SMB flush fid %d", fid);
 
        fid = smb_ChainFID(fid, inp);
     fidp = smb_FindFID(vcp, fid, 0);
@@ -4296,17 +4607,17 @@ int smb_FullNameProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
        char shortName[13];
        struct smb_FullNameRock *vrockp;
 
-       vrockp = rockp;
+       vrockp = (struct smb_FullNameRock *)rockp;
 
        if (!cm_Is8Dot3(dep->name)) {
                cm_Gen8Dot3Name(dep, shortName, NULL);
 
-               if (strcmp(shortName, vrockp->name) == 0) {
+               if (cm_stricmp(shortName, vrockp->name) == 0) {
                        vrockp->fullName = strdup(dep->name);
                        return CM_ERROR_STOPNOW;
                }
        }
-       if (stricmp(dep->name, vrockp->name) == 0
+       if (cm_stricmp(dep->name, vrockp->name) == 0
            && ntohl(dep->fid.vnode) == vrockp->vnode->fid.vnode
            && ntohl(dep->fid.unique) == vrockp->vnode->fid.unique) {
                vrockp->fullName = strdup(dep->name);
@@ -4346,7 +4657,7 @@ long smb_ReceiveCoreClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        fid = smb_GetSMBParm(inp, 0);
        dosTime = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
         
-       osi_Log1(afsd_logp, "SMB close fid %d", fid);
+       osi_Log1(smb_logp, "SMB close fid %d", fid);
 
        fid = smb_ChainFID(fid, inp);
     fidp = smb_FindFID(vcp, fid, 0);
@@ -4829,7 +5140,7 @@ long smb_ReceiveCoreWrite(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     op = smb_GetSMBData(inp, NULL);
        op = smb_ParseDataBlock(op, NULL, &inDataBlockCount);
 
-    osi_Log3(afsd_logp, "smb_ReceiveCoreWrite fd %d, off 0x%x, size 0x%x",
+    osi_Log3(smb_logp, "smb_ReceiveCoreWrite fd %d, off 0x%x, size 0x%x",
              fd, offset.LowPart, count);
         
        fd = smb_ChainFID(fd, inp);
@@ -4914,7 +5225,7 @@ void smb_CompleteWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
        fd = smb_GetSMBParm(inp, 0);
        fidp = smb_FindFID(vcp, fd, 0);
 
-       osi_Log2(afsd_logp, "Completing Raw Write offset %x count %x",
+       osi_Log2(smb_logp, "Completing Raw Write offset %x count %x",
                 rwcp->offset.LowPart, rwcp->count);
 
        userp = smb_GetUser(vcp, inp);
@@ -4995,7 +5306,7 @@ long smb_ReceiveCoreWriteRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
        op = (char *) inp->data;
        op += smb_GetSMBParm(inp, 11);
 
-    osi_Log4(afsd_logp,
+    osi_Log4(smb_logp,
              "smb_ReceiveCoreWriteRaw fd %d, off 0x%x, size 0x%x, WriteMode 0x%x",
              fd, offset.LowPart, count, writeMode);
         
@@ -5100,7 +5411,7 @@ long smb_ReceiveCoreRead(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     offset.HighPart = 0;       /* too bad */
     offset.LowPart = smb_GetSMBParm(inp, 2) | (smb_GetSMBParm(inp, 3) << 16);
         
-    osi_Log3(afsd_logp, "smb_ReceiveCoreRead fd %d, off 0x%x, size 0x%x",
+    osi_Log3(smb_logp, "smb_ReceiveCoreRead fd %d, off 0x%x, size 0x%x",
              fd, offset.LowPart, count);
         
        fd = smb_ChainFID(fd, inp);
@@ -5207,7 +5518,7 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp
         lastNamep = pathp;
     else 
         lastNamep++;
-    code = cm_Lookup(dscp, lastNamep, caseFold, userp, &req, &scp);
+    code = cm_Lookup(dscp, lastNamep, 0, userp, &req, &scp);
     if (scp) cm_ReleaseSCache(scp);
     if (code != CM_ERROR_NOSUCHFILE) {
         if (code == 0) code = CM_ERROR_EXISTS;
@@ -5314,7 +5625,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     if (!smb_IsLegalFilename(lastNamep))
         return CM_ERROR_BADNTFILENAME;
 
-    osi_Log1(afsd_logp, "SMB receive create [%s]", osi_LogSaveString( afsd_logp, pathp ));
+    osi_Log1(smb_logp, "SMB receive create [%s]", osi_LogSaveString( smb_logp, pathp ));
 #ifdef DEBUG_VERBOSE
     {
         char *hexp;
@@ -5324,7 +5635,7 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
     }
 #endif    
 
-    code = cm_Lookup(dscp, lastNamep, caseFold, userp, &req, &scp);
+    code = cm_Lookup(dscp, lastNamep, 0, userp, &req, &scp);
     if (code && code != CM_ERROR_NOSUCHFILE) {
                cm_ReleaseSCache(dscp);
         cm_ReleaseUser(userp);
@@ -5472,7 +5783,6 @@ long smb_ReceiveCoreSeek(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
        NCB *ncbp, raw_write_cont_t *rwcp)
 {
-    static showErrors = 0;
     smb_dispatch_t *dp;
     smb_t *smbp;
     unsigned long code = 0;
@@ -5546,7 +5856,7 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
         /* process each request in the packet; inCom, wctp and inCount
          * are already set up.
          */
-               osi_Log2(afsd_logp, "SMB received op 0x%x lsn %d", inp->inCom,
+               osi_Log2(smb_logp, "SMB received op 0x%x lsn %d", inp->inCom,
                  ncbp->ncb_lsn);
 
                /* now do the dispatch */
@@ -5580,10 +5890,10 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                                                 rwcp);
                        else {
                                        osi_LogEvent("AFS Dispatch %s",(myCrt_Dispatch(inp->inCom)),"vcp[%x] lana[%d] lsn[%d]",(int)vcp,vcp->lana,vcp->lsn);
-                                       osi_Log4(afsd_logp,"Dispatch %s vcp[%x] lana[%d] lsn[%d]",(myCrt_Dispatch(inp->inCom)),vcp,vcp->lana,vcp->lsn);
+                                       osi_Log4(smb_logp,"Dispatch %s vcp[%x] lana[%d] lsn[%d]",(myCrt_Dispatch(inp->inCom)),vcp,vcp->lana,vcp->lsn);
                                        code = (*(dp->procp)) (vcp, inp, outp);
                                        osi_LogEvent("AFS Dispatch return",NULL,"Code[%d]",(code==0)?0:code-CM_ERROR_BASE);
-                                       osi_Log1(afsd_logp,"Dispatch return  code[%d]",(code==0)?0:code-CM_ERROR_BASE);
+                                       osi_Log1(smb_logp,"Dispatch return  code[%d]",(code==0)?0:code-CM_ERROR_BASE);
             }
 
                        if (oldGen != sessionGen) {
@@ -5600,7 +5910,7 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                             1005, NULL, 1, ncbp->ncb_length, ptbuf, smbp);
                                DeregisterEventSource(h);
 #else /* DJGPP */
-                               osi_Log1(afsd_logp, "Pkt straddled session startup, "
+                               osi_Log1(smb_logp, "Pkt straddled session startup, "
                          "ncb length %d", ncbp->ncb_length);
 #endif /* !DJGPP */
                        }
@@ -5615,7 +5925,7 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                        if (showErrors) {
                                sprintf(tbuffer, "Received bad SMB req 0x%x", inp->inCom);
                 code = (*smb_MBfunc)(NULL, tbuffer, "Cancel: don't show again",
-                                     MB_OKCANCEL);
+                                     MB_OKCANCEL|MB_SERVICE_NOTIFICATION);
                 if (code == IDCANCEL) showErrors = 0;
                        }
 #endif /* DJGPP */
@@ -5644,7 +5954,7 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
             smb_LogPacket(inp);
 #endif /* NOTSERVICE */
 #else /* DJGPP */
-            osi_Log1(afsd_logp, "Invalid SMB message, length %d",
+            osi_Log1(smb_logp, "Invalid SMB message, length %d",
                      ncbp->ncb_length);
 #endif /* !DJGPP */
 
@@ -5666,9 +5976,11 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
                                outWctp = outp->wctp;
                                smbp = (smb_t *) &outp->data;
                                if (code != CM_ERROR_PARTIALWRITE
-                                   && code != CM_ERROR_BUFFERTOOSMALL) {
+                                   && code != CM_ERROR_BUFFERTOOSMALL 
+                    && code != CM_ERROR_GSSCONTINUE) {
                                        /* nuke wct and bcc.  For a partial
-                                        * write, assume they're OK.
+                                        * write or an in-process authentication handshake, 
+                     * assume they're OK.
                                         */
                                        *outWctp++ = 0;
                                        *outWctp++ = 0;
@@ -5760,11 +6072,19 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
        thrd_Decrement(&ongoingOps);
 
        if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
+        if (active_vcp) {
+            smb_ReleaseVC(active_vcp);
+            osi_Log2(smb_logp,
+                      "Replacing active_vcp %x with %x", active_vcp, vcp);
+        }
+        smb_HoldVC(vcp);
                active_vcp = vcp;
                last_msg_time = GetCurrentTime();
        }
-       else if (active_vcp == vcp)
+       else if (active_vcp == vcp) {
+        smb_ReleaseVC(active_vcp);
                active_vcp = NULL;
+    }
 
     return;
 }
@@ -5963,7 +6283,7 @@ void smb_Server(VOID *parmp)
     DWORD code, rcode;
     int idx_NCB, idx_session;
        UCHAR rc;
-       smb_vc_t *vcp;
+       smb_vc_t *vcp = NULL;
        smb_t *smbp;
 #ifdef DJGPP
     dos_ptr dos_ncb;
@@ -5981,7 +6301,7 @@ void smb_Server(VOID *parmp)
                        if (tod > EXPIREDATE) {
                                (*smb_MBfunc)(NULL, "AFS demo expiration",
                                           "afsd dispatcher",
-                                          MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);
+                                          MB_OK|MB_ICONSTOP|MB_SETFOREGROUND|MB_SERVICE_NOTIFICATION);
                                trhd_Exit(1);
                        }
                }
@@ -6034,7 +6354,7 @@ void smb_Server(VOID *parmp)
                rc = ncbp->ncb_retcode;
 
                if (rc != NRC_PENDING && rc != NRC_GOODRET)
-                       osi_Log1(afsd_logp, "NCBRECV failure code %d", rc);
+                       osi_Log1(smb_logp, "NCBRECV failure code %d", rc);
 
                switch (rc) {
                        case NRC_GOODRET: break;
@@ -6053,8 +6373,11 @@ void smb_Server(VOID *parmp)
                     afsi_log("session [ %d ] closed", idx_session);
                 }
                                dead_sessions[idx_session] = TRUE;
+                if (vcp)
+                    smb_ReleaseVC(vcp);
                                vcp = smb_FindVC(ncbp->ncb_lsn, 0, lanas[idx_session]);
-                               /* Should also release vcp.  Also, would do
+                               /* Should also release vcp.  [done] 2004-05-11 jaltman
+                 * Also, should do
                                 * sanity check that all TID's are gone. 
                  *
                  * TODO: check if we could use LSNs[idx_session] instead, 
@@ -6062,13 +6385,14 @@ void smb_Server(VOID *parmp)
                  */
                 if (vcp) {
                     if (dead_vcp)
-                        osi_Log1(afsd_logp,
+                        osi_Log1(smb_logp,
                                   "dead_vcp already set, %x",
                                   dead_vcp);
                     if (!dead_vcp && !(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
-                        osi_Log2(afsd_logp,
+                        osi_Log2(smb_logp,
                                   "setting dead_vcp %x, user struct %x",
                                   vcp, vcp->usersp);
+                        smb_HoldVC(vcp);
                         dead_vcp = vcp;
                         vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
                     }
@@ -6125,7 +6449,7 @@ void smb_Server(VOID *parmp)
                        default:
                                /* A weird error code.  Log it, sleep, and
                                 * continue. */
-                               if (vcp->errorCount++ > 3) {
+                               if (vcp && vcp->errorCount++ > 3) {
                     afsi_log("session [ %d ] closed, vcp->errorCount = %d", idx_session, vcp->errorCount);
                                        dead_sessions[idx_session] = TRUE;
                 }
@@ -6142,6 +6466,8 @@ void smb_Server(VOID *parmp)
                if (smb_concurrentCalls > smb_maxObsConcurrentCalls)
                        smb_maxObsConcurrentCalls = smb_concurrentCalls;
 
+        if (vcp)
+            smb_ReleaseVC(vcp);
                vcp = smb_FindVC(ncbp->ncb_lsn, 0, ncbp->ncb_lana_num);
         /*
                * If at this point vcp is NULL (implies that packet was invalid)
@@ -6179,7 +6505,7 @@ void smb_Server(VOID *parmp)
                        }
 
                        /* Also log in the trace log. */
-                       osi_Log4(afsd_logp, "Server: BAD VCP!"
+                       osi_Log4(smb_logp, "Server: BAD VCP!"
                                "LSNs[idx_session]=[%d],"
                                "lanas[idx_session]=[%d],"
                                "ncbp->ncb_lsn=[%d],"
@@ -6265,6 +6591,8 @@ void smb_Server(VOID *parmp)
 doneWithNCB:
                thrd_SetEvent(NCBavails[idx_NCB]);
        }
+    if (vcp)
+        smb_ReleaseVC(vcp);
 }
 
 /*
@@ -6370,7 +6698,7 @@ void smb_Listener(void *parmp)
                        if (tod > EXPIREDATE) {
                                (*smb_MBfunc)(NULL, "AFS demo expiration",
                                "afsd listener",
-                               MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);
+                               MB_OK|MB_ICONSTOP|MB_SETFOREGROUND|MB_SERVICE_NOTIFICATION);
 #ifndef DJGPP
                 ExitThread(1);
 #else
@@ -6402,7 +6730,11 @@ void smb_Listener(void *parmp)
 
         if (code != 0)
         {
-                   /* terminate if shutdown flag is set */
+#ifndef DJGPP
+            char tbuffer[256];
+#endif
+
+            /* terminate silently if shutdown flag is set */
                if (smbShutdownFlag == 1) {
 #ifndef DJGPP
                            ExitThread(1);
@@ -6411,17 +6743,29 @@ void smb_Listener(void *parmp)
 #endif
                        }
 
+            osi_Log2(smb_logp, 
+                     "NCBLISTEN lana=%d failed with code %d",
+                     ncbp->ncb_lana_num, code);
+            osi_Log0(smb_logp, 
+                     "Client exiting due to network failure. Please restart client.\n");
+
 #ifndef DJGPP
-                       osi_assert(0);
+            sprintf(tbuffer, 
+                     "Client exiting due to network failure.  Please restart client.\n"
+                     "NCBLISTEN lana=%d failed with code %d",
+                     ncbp->ncb_lana_num, code);
+                       if (showErrors)
+                code = (*smb_MBfunc)(NULL, tbuffer, "AFS Client Service: Fatal Error",
+                                     MB_OK|MB_SERVICE_NOTIFICATION);
+            osi_assert(tbuffer);
+            ExitThread(1);
 #else
             fprintf(stderr, "NCBLISTEN lana=%d failed with code %d\n",
                      ncbp->ncb_lana_num, code);
-            osi_Log2(0, "NCBLISTEN lana=%d failed with code %d",
-                      ncbp->ncb_lana_num, code);
             fprintf(stderr, "\nClient exiting due to network failure "
                      "(possibly due to power-saving mode)\n");
             fprintf(stderr, "Please restart client.\n");
-            afs_exit(AFS_EXITCODE_NETWORK_FAILURE);
+                       afs_exit(AFS_EXITCODE_NETWORK_FAILURE);
 #endif /* !DJGPP */
         }
 
@@ -6440,7 +6784,7 @@ void smb_Listener(void *parmp)
                        if (strncmp(rname, cname, NCBNAMSZ) != 0)
                                flags |= SMB_VCFLAG_REMOTECONN;
 
-               osi_Log1(afsd_logp, "New session lsn %d", ncbp->ncb_lsn);
+               osi_Log1(smb_logp, "New session lsn %d", ncbp->ncb_lsn);
                /* lock */
                lock_ObtainMutex(&smb_ListenerLock);
 
@@ -6470,7 +6814,7 @@ void smb_Listener(void *parmp)
                        DeregisterEventSource(h);
 #else /* DJGPP */
             afsi_log("NCBLISTEN completed, call from %s",rname);
-            osi_Log1(afsd_logp, "SMB session startup, %d ongoing ops",
+            osi_Log1(smb_logp, "SMB session startup, %d ongoing ops",
                      ongoingOps);
             time(&now);
             fprintf(stderr, "%s: New session %d starting from host %s\n",
@@ -6500,7 +6844,8 @@ void smb_Listener(void *parmp)
          * we run out.
          */
 
-        osi_assert(i < Sessionmax && numNCBs < NCBmax - 1);
+        osi_assert(i < Sessionmax - 1);
+        osi_assert(numNCBs < NCBmax - 1);   /* if we pass this test we can allocate one more */
 
                LSNs[i] = ncbp->ncb_lsn;
                lanas[i] = ncbp->ncb_lana_num;
@@ -6509,7 +6854,7 @@ void smb_Listener(void *parmp)
                        /* Add new NCB for new session */
             char eventName[MAX_PATH];
 
-            osi_Log1(afsd_logp, "smb_Listener creating new session %d", i);
+            osi_Log1(smb_logp, "smb_Listener creating new session %d", i);
 
                        InitNCBslot(numNCBs);
                        numNCBs++;
@@ -6743,7 +7088,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
                if (tod > EXPIREDATE) {
 #ifndef DJGPP
                        (*smb_MBfunc)(NULL, "AFS demo expiration", "afsd",
-                          MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);
+                          MB_OK|MB_ICONSTOP|MB_SETFOREGROUND|MB_SERVICE_NOTIFICATION);
                        exit(1);
 #else /* DJGPP */
             fprintf(stderr, "AFS demo expiration\n");
@@ -6837,6 +7182,7 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
     smb_NetbiosInit();
 
        /* Initialize listener and server structures */
+    numVCs = 0;
        memset(dead_sessions, 0, sizeof(dead_sessions));
     sprintf(eventName, "SessionEvents[0]");
        SessionEvents[0] = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
@@ -6950,6 +7296,69 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
 
        smb3_Init();
 
+       /* if we are doing SMB authentication we have register outselves as a logon process */
+       if (smb_authType != SMB_AUTH_NONE) {
+        NTSTATUS nts;
+               LSA_STRING afsProcessName;
+               LSA_OPERATIONAL_MODE dummy; /*junk*/
+               DWORD bufsize;
+
+               afsProcessName.Buffer = "OpenAFSClientDaemon";
+               afsProcessName.Length = strlen(afsProcessName.Buffer);
+               afsProcessName.MaximumLength = afsProcessName.Length + 1;
+
+               nts = LsaRegisterLogonProcess(&afsProcessName, &smb_lsaHandle, &dummy);
+
+               if (nts == STATUS_SUCCESS) {
+                       LSA_STRING packageName;
+                       /* we are registered. Find out the security package id */
+                       packageName.Buffer = MSV1_0_PACKAGE_NAME;
+                       packageName.Length = strlen(packageName.Buffer);
+                       packageName.MaximumLength = packageName.Length + 1;
+                       nts = LsaLookupAuthenticationPackage(smb_lsaHandle, &packageName , &smb_lsaSecPackage);
+                       if (nts == STATUS_SUCCESS) {
+                               /* Now get ourselves a domain name. */
+                               /* For now we are using the local computer name as the domain name.
+                                * It is actually the domain for local logins, and we are acting as
+                                * a local SMB server. 
+                 */
+                               bufsize = sizeof(smb_ServerDomainName) - 1;
+                               GetComputerName(smb_ServerDomainName, &bufsize);
+                               smb_ServerDomainNameLength = bufsize + 1; /* bufsize doesn't include terminator */
+                               afsi_log("Setting SMB server domain name to [%s]", smb_ServerDomainName);
+
+                               smb_lsaLogonOrigin.Buffer = "OpenAFS";
+                               smb_lsaLogonOrigin.Length = strlen(smb_lsaLogonOrigin.Buffer);
+                               smb_lsaLogonOrigin.MaximumLength = smb_lsaLogonOrigin.Length + 1;
+                       } else {
+                               afsi_log("Can't determine security package name for NTLM!! NTSTATUS=[%l]",nts);
+                       }
+               } else {
+                       afsi_log("Can't register logon process!! NTSTATUS=[%l]",nts);
+               }
+
+               if (nts != STATUS_SUCCESS) {
+                       /* something went wrong. We report the error and revert back to no authentication
+                          because we can't perform any auth requests without a successful lsa handle
+                          or sec package id. */
+                       afsi_log("Reverting to NO SMB AUTH");
+                       smb_authType = SMB_AUTH_NONE;
+               } else if ( smb_authType == SMB_AUTH_EXTENDED) {
+            /* Test to see if there is anything to negotiate.  If SPNEGO is not going to be used 
+            * then the only option is NTLMSSP anyway; so just fallback. 
+            */
+            void * secBlob;
+            int secBlobLength;
+
+            smb_NegotiateExtendedSecurity(&secBlob, &secBlobLength);
+            if (secBlobLength == 0) {
+                smb_authType = SMB_AUTH_NTLM;
+                afsi_log("Reverting to SMB AUTH NTLM");
+            } else
+                free(secBlob);
+        }
+       }
+
        /* Start listeners, waiters, servers, and daemons */
 
        for (i = 0; i < lana_list.length; i++) {
@@ -7035,7 +7444,7 @@ void smb_Shutdown(void)
         /*fprintf(stderr, "returned from NCBHANGUP session %d LSN %d\n", i, LSNs[i]);*/
         if (code == 0) code = ncbp->ncb_retcode;
         if (code != 0) {
-            osi_Log1(afsd_logp, "Netbios NCBHANGUP error code %d", code);
+            osi_Log1(smb_logp, "Netbios NCBHANGUP error code %d", code);
             fprintf(stderr, "Session %d Netbios NCBHANGUP error code %d", i, code);
         }
     }
@@ -7089,7 +7498,7 @@ void smb_LogPacket(smb_packet_t *packet)
 
        if(!packet) return;
 
-       osi_Log0(afsd_logp, "*** SMB packet dump ***");
+       osi_Log0(smb_logp, "*** SMB packet dump ***");
 
        vp = (BYTE *) packet->data;
 
@@ -7134,10 +7543,10 @@ void smb_LogPacket(smb_packet_t *packet)
 
                *cp = 0;
 
-               osi_Log0( afsd_logp, buf );
+               osi_Log0( smb_logp, buf );
        }
 
-       osi_Log0(afsd_logp, "*** End SMB packet dump ***");
+       osi_Log0(smb_logp, "*** End SMB packet dump ***");
 
 }
 
@@ -7152,6 +7561,9 @@ int smb_DumpVCP(FILE *outputFile, char *cookie)
   
     lock_ObtainRead(&smb_rctLock);
   
+    sprintf(output, "begin dumping vcpsp\n");
+    WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+
     for(vcp = smb_allVCsp; vcp; vcp=vcp->nextp) 
     {
         smb_fid_t *fidp;
@@ -7160,7 +7572,10 @@ int smb_DumpVCP(FILE *outputFile, char *cookie)
                  cookie, vcp, vcp->refCount, vcp->flags, vcp->vcID, vcp->lsn, vcp->uidCounter, vcp->tidCounter, vcp->fidCounter);
         WriteFile(outputFile, output, strlen(output), &zilch, NULL);
       
-        for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) 
+        sprintf(output, "begin dumping fidsp\n");
+        WriteFile(outputFile, output, strlen(output), &zilch, NULL);
+
+        for (fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q))
         {
             sprintf(output, "%s -- fidp=0x%08X, refCount=%d, fid=%d, vcp=0x%08X, scp=0x%08X, ioctlp=0x%08X, NTopen_pathp=%s, NTopen_wholepathp=%s\n", 
                      cookie, fidp, fidp->refCount, fidp->fid, fidp->vcp, fidp->scp, fidp->ioctlp, 
@@ -7171,7 +7586,10 @@ int smb_DumpVCP(FILE *outputFile, char *cookie)
       
         sprintf(output, "done dumping fidsp\n");
         WriteFile(outputFile, output, strlen(output), &zilch, NULL);
-    }       
+    }
+
+    sprintf(output, "done dumping vcpsp\n");
+    WriteFile(outputFile, output, strlen(output), &zilch, NULL);
   
     lock_ReleaseRead(&smb_rctLock);
     return 0;