windows-updates-20021104
[openafs.git] / src / WINNT / afsd / smb3.c
index f606728..98ddb09 100644 (file)
@@ -7,10 +7,14 @@
  * directory or online at http://www.openafs.org/dl/license10.html
  */
 
+//#define NOSERVICE 1 
+
 #include <afs/param.h>
 #include <afs/stds.h>
 
+#ifndef DJGPP
 #include <windows.h>
+#endif /* !DJGPP */
 #include <stdlib.h>
 #include <malloc.h>
 #include <string.h>
@@ -40,14 +44,16 @@ smb_tran2Packet_t *smb_tran2AssemblyQueuep;
 cm_user_t *smb_GetTran2User(smb_vc_t *vcp, smb_tran2Packet_t *inp)
 {
        smb_user_t *uidp;
-        cm_user_t *up;
+        cm_user_t *up = NULL;
         
         uidp = smb_FindUID(vcp, inp->uid, 0);
         if (!uidp) return NULL;
         
        lock_ObtainMutex(&uidp->mx);
-        up = uidp->userp;
-        cm_HoldUser(up);
+        if (uidp->unp) {
+          up = uidp->unp->userp;
+          cm_HoldUser(up);
+        }
        lock_ReleaseMutex(&uidp->mx);
 
         smb_ReleaseUID(uidp);
@@ -105,119 +111,88 @@ unsigned char *smb_ParseString(unsigned char *inp, char **chainpp)
 
 long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-       char *tp;
-       char *usern, *pwd, *pwdx;
-       smb_user_t *uidp, *dead_uidp;
-       unsigned short newUid;
-       unsigned long caps;
-       cm_user_t *userp;
-       char *s1 = " ";
-
-       /* Check for bad conns */
-       if (vcp->flags & SMB_VCFLAG_REMOTECONN)
-               return CM_ERROR_REMOTECONN;
-
-       /* For NT LM 0.12 and up, get capabilities */
-       if (vcp->flags & SMB_VCFLAG_USENT) {
-               caps = smb_GetSMBParm(inp, 11);
-               if (caps & 0x40)
-                       vcp->flags |= SMB_VCFLAG_STATUS32;
-               /* for now, ignore other capability bits */
-       }
-
-       /* Parse the data */
-       tp = smb_GetSMBData(inp, NULL);
-       if (vcp->flags & SMB_VCFLAG_USENT)
-               pwdx = smb_ParseString(tp, &tp);
-       pwd = smb_ParseString(tp, &tp);
-       usern = smb_ParseString(tp, &tp);
-
-       /* Create a new UID and cm_user_t structure */
-       userp = cm_NewUser();
-       lock_ObtainMutex(&vcp->mx);
-       newUid = vcp->uidCounter++;
-       lock_ReleaseMutex(&vcp->mx);
-
-       /* Create a new smb_user_t structure and connect them up */
-       uidp = smb_FindUID(vcp, newUid, SMB_FLAG_CREATE);
-       lock_ObtainMutex(&uidp->mx);
-       uidp->userp = userp;
-       uidp->name = strdup(usern);
-       lock_ReleaseMutex(&uidp->mx);
-       smb_ReleaseUID(uidp);
-        
-       if (dead_vcp) {
-               dead_uidp = dead_vcp->usersp;
-               while (dead_uidp) {
-                       if (dead_uidp->userp
-                           && strcmp(dead_uidp->name, usern) == 0)
-                               break;
-                       dead_uidp = dead_uidp->nextp;
-               }
-       }
-
-       /* transfer tokens from dead vcp */
-       if (dead_vcp && dead_uidp) {
-               cm_user_t *dead_userp;
-               s1 = ", tokens from terminated session";
-               dead_userp = dead_uidp->userp;
-               cm_ResetACLCache(dead_userp);
-               userp->cellInfop = dead_userp->cellInfop;
-               dead_userp->cellInfop = NULL;
-               dead_vcp = NULL;
-       }
-
-       /* transfer tokens from integrated logon */
-       if (vcp->logonDLLUser) {
-               s1 = ", tokens from integrated logon";
-               cm_ResetACLCache(vcp->logonDLLUser);
-               userp->cellInfop = vcp->logonDLLUser->cellInfop;
-               vcp->logonDLLUser->cellInfop = NULL;
-               vcp->logonDLLUser = NULL;
-       }
-
-       /* transfer tokens for logoff profile upload */
-       if (vcp->justLoggedOut) {
-               cm_user_t *logout_userp;
-               if (GetTickCount() - vcp->logoffTime <
-                       1000 * smb_LogoffTransferTimeout
-                   && strcmp(vcp->justLoggedOut->name, usern) == 0) {
-                       s1 = ", tokens from logoff";
-                       logout_userp = vcp->justLoggedOut->userp;
-                       cm_ResetACLCache(logout_userp);
-                       userp->cellInfop = logout_userp->cellInfop;
-                       logout_userp->cellInfop = NULL;
-               }
-               vcp->justLoggedOut = NULL;
-       }
-       else if (loggedOut) {
-               cm_user_t *logout_userp;
-               if (GetTickCount() - loggedOutTime <
-                       1000 * smb_LogoffTransferTimeout
-                   && strcmp(loggedOutName, usern) == 0) {
-                       s1 = ", tokens from logoff";
-                       logout_userp = loggedOutUserp->userp;
-                       cm_ResetACLCache(logout_userp);
-                       userp->cellInfop = logout_userp->cellInfop;
-                       logout_userp->cellInfop = NULL;
-               }
-               smb_ReleaseUID(loggedOutUserp);
-               loggedOutUserp = NULL;
-               free(loggedOutName);
-               loggedOutName = NULL;
-               loggedOut = 0;
-       }
-
-       /* Return UID to the client */
-       ((smb_t *)outp)->uid = newUid;
-       /* Also to the next chained message */
-       ((smb_t *)inp)->uid = newUid;
-
-       osi_Log3(afsd_logp, "SMB3 session setup name %s creating ID %d%s",
-                       osi_LogSaveString(afsd_logp, usern), newUid, osi_LogSaveString(afsd_logp, s1));
-       smb_SetSMBParm(outp, 2, 0);
-        smb_SetSMBDataLength(outp, 0);
-        return 0;
+    char *tp;
+    char *usern, *pwd, *pwdx;
+    smb_user_t *uidp, *dead_uidp;
+    unsigned short newUid;
+    unsigned long caps;
+    cm_user_t *userp;
+    smb_username_t *unp;
+    char *s1 = " ";
+
+    /* Check for bad conns */
+    if (vcp->flags & SMB_VCFLAG_REMOTECONN)
+        return CM_ERROR_REMOTECONN;
+
+    /* For NT LM 0.12 and up, get capabilities */
+    if (vcp->flags & SMB_VCFLAG_USENT) {
+        caps = smb_GetSMBParm(inp, 11);
+        if (caps & 0x40)
+            vcp->flags |= SMB_VCFLAG_STATUS32;
+        /* for now, ignore other capability bits */
+    }
+
+    /* Parse the data */
+    tp = smb_GetSMBData(inp, NULL);
+    if (vcp->flags & SMB_VCFLAG_USENT)
+        pwdx = smb_ParseString(tp, &tp);
+    pwd = smb_ParseString(tp, &tp);
+    usern = smb_ParseString(tp, &tp);
+
+    /* On Windows 2000, this function appears to be called more often than
+       it is expected to be called. This resulted in multiple smb_user_t
+       records existing all for the same user session which results in all
+       of the users tokens disappearing.
+
+       To avoid this problem, we look for an existing smb_user_t record
+       based on the users name, and use that one if we find it.
+    */
+
+    uidp = smb_FindUserByNameThisSession(vcp, usern);
+    if (uidp) {   /* already there, so don't create a new one */
+        unp = uidp->unp;
+        userp = unp->userp;
+        newUid = (unsigned short)uidp->userID;  /* For some reason these are different types!*/
+               osi_LogEvent("AFS smb_ReceiveV3SessionSetupX",NULL,"FindUserByName:Lana[%d],lsn[%d],userid[%d],name[%s]",vcp->lana,vcp->lsn,newUid,usern);
+               osi_Log3(afsd_logp,"smb_ReceiveV3SessionSetupX FindUserByName:Lana[%d],lsn[%d],userid[%d]",vcp->lana,vcp->lsn,newUid);
+        smb_ReleaseUID(uidp);
+    }
+    else {
+      /* do a global search for the username/machine name pair */
+        unp = smb_FindUserByName(usern, vcp->rname, SMB_FLAG_CREATE);
+
+        /* Create a new UID and cm_user_t structure */
+        userp = unp->userp;
+        if (!userp)
+          userp = cm_NewUser();
+        lock_ObtainMutex(&vcp->mx);
+        newUid = (strlen(usern)==0)?0:vcp->uidCounter++;
+        lock_ReleaseMutex(&vcp->mx);
+
+        /* Create a new smb_user_t structure and connect them up */
+        lock_ObtainMutex(&unp->mx);
+        unp->userp = userp;
+        lock_ReleaseMutex(&unp->mx);
+
+        uidp = smb_FindUID(vcp, newUid, SMB_FLAG_CREATE);
+        lock_ObtainMutex(&uidp->mx);
+        uidp->unp = unp;
+               osi_LogEvent("AFS smb_ReceiveV3SessionSetupX",NULL,"MakeNewUser:VCP[%x],Lana[%d],lsn[%d],userid[%d],TicketKTCName[%s]",vcp,vcp->lana,vcp->lsn,newUid,usern);
+               osi_Log4(afsd_logp,"smb_ReceiveV3SessionSetupX MakeNewUser:VCP[%x],Lana[%d],lsn[%d],userid[%d]",vcp,vcp->lana,vcp->lsn,newUid);
+        lock_ReleaseMutex(&uidp->mx);
+        smb_ReleaseUID(uidp);
+    }
+
+    /* Return UID to the client */
+    ((smb_t *)outp)->uid = newUid;
+    /* Also to the next chained message */
+    ((smb_t *)inp)->uid = newUid;
+
+    osi_Log3(afsd_logp, "SMB3 session setup name %s creating ID %d%s",
+             osi_LogSaveString(afsd_logp, usern), newUid, osi_LogSaveString(afsd_logp, s1));
+    smb_SetSMBParm(outp, 2, 0);
+    smb_SetSMBDataLength(outp, 0);
+    return 0;
 }
 
 long smb_ReceiveV3UserLogoffX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
@@ -234,27 +209,13 @@ long smb_ReceiveV3UserLogoffX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou
         if (uidp) {
                char *s1 = NULL, *s2 = NULL;
 
-               /* Also, this is not logon session any more */
-               if (uidp->userp == vcp->logonDLLUser) {
-                       s1 = ", was logon session";
-                       vcp->logonDLLUser = NULL;
-               }
-
-               /* But its tokens might be needed later */
-               if (uidp->userp && !(uidp->userp->flags & CM_USERFLAG_WASLOGON)
-                   && smb_LogoffTokenTransfer) {
-                       s2 = ", pre-logout effect";
-                       vcp->justLoggedOut = uidp;
-                       vcp->logoffTime = GetTickCount();
-               }
-
                if (s2 == NULL) s2 = " ";
                if (s1 == NULL) {s1 = s2; s2 = " ";}
 
                osi_Log4(afsd_logp, "SMB3 user logoffX uid %d name %s%s%s",
                         uidp->userID,
-                        osi_LogSaveString(afsd_logp, uidp->name),
-                        s1, s2);
+                        osi_LogSaveString(afsd_logp,
+                 (uidp->unp) ? uidp->unp->name: " "), s1, s2);
 
                lock_ObtainMutex(&uidp->mx);
                uidp->flags |= SMB_USERFLAG_DELETE;
@@ -549,6 +510,7 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 
        /* We sometimes see 0 word count.  What to do? */
        if (*inp->wctp == 0) {
+#ifndef DJGPP
                HANDLE h;
                char *ptbuf[1];
 
@@ -559,6 +521,9 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1003, NULL,
                            1, inp->ncb_length, ptbuf, inp);
                DeregisterEventSource(h);
+#else /* DJGPP */
+               osi_Log0(afsd_logp, "TRANSACTION2 word count = 0"); 
+#endif /* !DJGPP */
 
                 smb_SetSMBDataLength(outp, 0);
                 smb_SendPacket(vcp, outp);
@@ -619,6 +584,8 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                 lock_ReleaseWrite(&smb_globalLock);
                 
                 /* now dispatch it */
+                               osi_LogEvent("AFS-Dispatch-2[%s]",myCrt_2Dispatch(asp->opcode),"vcp[%x] lana[%d] lsn[%d]",vcp,vcp->lana,vcp->lsn);
+                               osi_Log4(afsd_logp,"AFS Server - Dispatch-2 %s vcp[%x] lana[%d] lsn[%d]",myCrt_2Dispatch(asp->opcode),vcp,vcp->lana,vcp->lsn);
                 code = (*smb_tran2DispatchTable[asp->opcode].procp)(vcp, asp, outp);
 
                /* if an error is returned, we're supposed to send an error packet,
@@ -1042,7 +1009,7 @@ struct smb_ShortNameRock {
        size_t shortNameLen;
 };
 
-long cm_GetShortNameProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *vrockp,
+int cm_GetShortNameProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *vrockp,
        osi_hyper_t *offp)
 {
        struct smb_ShortNameRock *rockp;
@@ -1181,7 +1148,9 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                spacep = cm_GetSpace();
                smb_StripLastComponent(spacep->data, &lastComp,
                                        (char *)(&p->parmsp[3]));
-               if (strcmp(lastComp, "\\desktop.ini") == 0) {
+               /* Make sure that lastComp is not NULL */
+               if (lastComp)
+                   if (strcmp(lastComp, "\\desktop.ini") == 0) {
                        code = cm_NameI(cm_rootSCachep, spacep->data,
                                        CM_FLAG_CASEFOLD
                                          | CM_FLAG_DIRSEARCH
@@ -1221,7 +1190,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                 smb_FreeTran2Packet(outp);
                 return 0;
         }
-        
+
         lock_ObtainMutex(&scp->mx);
         code = cm_SyncOp(scp, NULL, userp, &req, 0,
                CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
@@ -1235,7 +1204,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
        if (infoLevel == 0x108) {
                code = cm_GetShortName((char *)(&p->parmsp[3]), userp, &req,
                                        tidPathp, scp->fid.vnode, shortName,
-                                       &len);
+                                       (size_t *) &len);
                if (code) {
                        goto done;
                }
@@ -1478,13 +1447,18 @@ long smb_ReceiveTran2SetFileInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet
 
                /* prepare for setattr call */
                attr.mask = 0;
+               
                lastMod = *((FILETIME *)(p->datap + 16));
-               if (LargeIntegerNotEqualToZero(*((LARGE_INTEGER *)&lastMod))) {
+               /* when called as result of move a b, lastMod is (-1, -1). If the check for -1 is not present, timestamp
+               of the resulting file will be 1969 (-1)
+                */
+               if (LargeIntegerNotEqualToZero(*((LARGE_INTEGER *)&lastMod)) && lastMod.dwLowDateTime != -1 && lastMod.dwHighDateTime != -1) {
                        attr.mask |= CM_ATTRMASK_CLIENTMODTIME;
                        smb_UnixTimeFromLargeSearchTime(&attr.clientModTime,
                                                        &lastMod);
                        fidp->flags |= SMB_FID_MTIMESETDONE;
                }
+               
                attribute = *((u_long *)(p->datap + 32));
                if (attribute != 0) {
                        if ((scp->unixModeBits & 0222)
@@ -1888,6 +1862,8 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
        char shortName[13];             /* 8.3 name if needed */
        int NeedShortName;
        char *shortNameEnd;
+        int fileType;
+        cm_fid_t fid;
         
         cm_req_t req;
 
@@ -2199,6 +2175,24 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                        || (NeedShortName
                            && smb_V3MatchMask(shortName, maskp,
                                                CM_FLAG_CASEFOLD)))) {
+
+                        /* Eliminate entries that don't match requested
+                           attributes */
+                        if (!(dsp->attribute & 0x10))  /* no directories */
+                        {
+                            /* We have already done the cm_TryBulkStat above */
+                            fid.cell = scp->fid.cell;
+                            fid.volume = scp->fid.volume;
+                            fid.vnode = ntohl(dep->fid.vnode);
+                            fid.unique = ntohl(dep->fid.unique);
+                            fileType = cm_FindFileType(&fid);
+                            /*osi_Log2(afsd_logp, "smb_ReceiveTran2SearchDir: file %s "
+                              "has filetype %d", dep->name,
+                              fileType);*/
+                            if (fileType == CM_SCACHETYPE_DIRECTORY)
+                              goto nextEntry;
+                        }
+
                        /* finally check if this name will fit */
 
                        /* standard dir entry stuff */
@@ -2294,6 +2288,9 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t
                                curPatchp->fid.volume = scp->fid.volume;
                                curPatchp->fid.vnode = ntohl(dep->fid.vnode);
                                curPatchp->fid.unique = ntohl(dep->fid.unique);
+
+                                /* temp */
+                                curPatchp->dep = dep;
                        }
 
                        if (searchFlags & 4)
@@ -2367,7 +2364,8 @@ nextEntry:
          * we're supposed to close the search if we're done, and we're done,
          * or if something went wrong, close the search.
          */
-        if ((searchFlags & 1) || ((searchFlags & 2) && eos)
+        /* ((searchFlags & 1) || ((searchFlags & 2) && eos) */
+       if ((searchFlags & 1) || (returnedNames == 0)
                || code != 0) smb_DeleteDirSearch(dsp);
        if (code)
                smb_SendTran2Error(vcp, p, opx, code);
@@ -2959,7 +2957,11 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
        /* set the packet data length the count of the # of bytes */
         smb_SetSMBDataLength(outp, count);
 
+#ifndef DJGPP
        code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount);
+#else /* DJGPP */
+       code = smb_ReadData(fidp, &offset, count, op, userp, &finalCount, FALSE);
+#endif /* !DJGPP */
 
        /* fix some things up */
        smb_SetSMBParm(outp, 5, finalCount);
@@ -4104,3 +4106,22 @@ void smb3_Init()
 {
        lock_InitializeMutex(&smb_Dir_Watch_Lock, "Directory Watch List Lock");
 }
+
+cm_user_t *smb_FindCMUserByName(/*smb_vc_t *vcp,*/ char *usern, char *machine)
+{
+    cm_user_t *userp;
+    /*int newUid;*/
+    smb_username_t *unp;
+
+    unp = smb_FindUserByName(usern, machine, SMB_FLAG_CREATE);
+    if (!unp->userp) {
+        lock_ObtainMutex(&unp->mx);
+        unp->userp = cm_NewUser();
+        lock_ReleaseMutex(&unp->mx);
+               osi_LogEvent("AFS smb_FindCMUserByName New User",NULL,"name[%s] machine[%s]",usern,machine);
+    }  else    {
+               osi_LogEvent("AFS smb_FindCMUserByName Found",NULL,"name[%s] machine[%s]",usern,machine);
+       }
+    return unp->userp;
+}
+