#include <afs/param.h>
#include <afs/stds.h>
+#ifndef DJGPP
#include <windows.h>
+#endif /* !DJGPP */
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include "smb.h"
-extern smb_vc_t *dead_vcp;
-
extern osi_hyper_t hzero;
smb_packet_t *smb_Directory_Watches = NULL;
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);
if (scp->fileType == CM_SCACHETYPE_DIRECTORY
|| scp->fileType == CM_SCACHETYPE_MOUNTPOINT)
- attrs = 0x10;
+ attrs = SMB_ATTR_DIRECTORY;
else
attrs = 0;
/*
if ((scp->unixModeBits & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
#endif
if ((scp->unixModeBits & 0222) == 0)
- attrs |= 1; /* Read-only */
+ attrs |= SMB_ATTR_READONLY; /* Read-only */
if (attrs == 0)
- attrs = 0x80; /* FILE_ATTRIBUTE_NORMAL */
+ attrs = SMB_ATTR_NORMAL; /* FILE_ATTRIBUTE_NORMAL */
return attrs;
}
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;
+ 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);
+ if (!vcp->uidCounter)
+ vcp->uidCounter++; /* handle unlikely wraparounds */
+ 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]",(int)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)
inp->flags |= SMB_PACKETFLAG_PROFILE_UPDATE_OK;
/* find the tree and free it */
- uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
- if (uidp) {
+ uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
+ /* TODO: smb_ReleaseUID() ? */
+ 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;
int totalParms, int totalData)
{
smb_tran2Packet_t *tp;
- smb_t *smbp;
+ smb_t *smbp;
- smbp = (smb_t *) inp->data;
+ smbp = (smb_t *) inp->data;
tp = malloc(sizeof(*tp));
- memset(tp, 0, sizeof(*tp));
- tp->vcp = vcp;
- smb_HoldVC(vcp);
- tp->curData = tp->curParms = 0;
- tp->totalData = totalData;
- tp->totalParms = totalParms;
- tp->tid = smbp->tid;
- tp->mid = smbp->mid;
- tp->uid = smbp->uid;
- tp->pid = smbp->pid;
+ memset(tp, 0, sizeof(*tp));
+ tp->vcp = vcp;
+ smb_HoldVC(vcp);
+ tp->curData = tp->curParms = 0;
+ tp->totalData = totalData;
+ tp->totalParms = totalParms;
+ tp->tid = smbp->tid;
+ tp->mid = smbp->mid;
+ tp->uid = smbp->uid;
+ tp->pid = smbp->pid;
tp->res[0] = smbp->res[0];
osi_QAdd((osi_queue_t **)&smb_tran2AssemblyQueuep, &tp->q);
- tp->opcode = smb_GetSMBParm(inp, 14);
+ tp->opcode = smb_GetSMBParm(inp, 14);
if (totalParms != 0)
- tp->parmsp = malloc(totalParms);
+ tp->parmsp = malloc(totalParms);
if (totalData != 0)
- tp->datap = malloc(totalData);
+ tp->datap = malloc(totalData);
tp->flags |= SMB_TRAN2PFLAG_ALLOC;
- return tp;
+ return tp;
}
smb_tran2Packet_t *smb_GetTran2ResponsePacket(smb_vc_t *vcp,
/* free a tran2 packet; must be called with smb_globalLock held */
void smb_FreeTran2Packet(smb_tran2Packet_t *t2p)
{
- if (t2p->vcp) smb_ReleaseVC(t2p->vcp);
+ if (t2p->vcp) smb_ReleaseVC(t2p->vcp);
if (t2p->flags & SMB_TRAN2PFLAG_ALLOC) {
if (t2p->parmsp)
free(t2p->parmsp);
if (t2p->datap)
free(t2p->datap);
}
- free(t2p);
+ free(t2p);
}
/* called with a VC, an input packet to respond to, and an error code.
/* We sometimes see 0 word count. What to do? */
if (*inp->wctp == 0) {
+#ifndef DJGPP
HANDLE h;
char *ptbuf[1];
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);
parmCount, dataCount);
}
- /* now copy the parms and data */
+ /* now copy the parms and data */
+ if ( parmCount != 0 )
+ {
memcpy(((char *)asp->parmsp) + parmDisp, inp->data + parmOffset, parmCount);
+ }
+ if ( dataCount != 0 ) {
memcpy(asp->datap + dataDisp, inp->data + dataOffset, dataCount);
-
+ }
+
/* account for new bytes */
asp->curData += dataCount;
asp->curParms += parmCount;
osi_QRemove((osi_queue_t **) &smb_tran2AssemblyQueuep, &asp->q);
lock_ReleaseWrite(&smb_globalLock);
- /* now dispatch it */
+ /* now dispatch it */
+ if ( asp->opcode >= 0 && asp->opcode < 20 && smb_tran2DispatchTable[asp->opcode].procp) {
+ osi_LogEvent("AFS-Dispatch-2[%s]",myCrt_2Dispatch(asp->opcode),"vcp[%x] lana[%d] lsn[%d]",(int)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);
+ }
+ else {
+ osi_LogEvent("AFS-Dispatch-2 [invalid]", NULL, "op[%x] vcp[%x] lana[%d] lsn[%d]", asp->opcode, vcp, vcp->lana, vcp->lsn);
+ osi_Log4(afsd_logp,"AFS Server - Dispatch-2 [INVALID] op[%x] vcp[%x] lana[%d] lsn[%d]", asp->opcode, vcp, vcp->lana, vcp->lsn);
+ code = CM_ERROR_BADOP;
+ }
/* if an error is returned, we're supposed to send an error packet,
* otherwise the dispatched function already did the data sending.
return 0;
}
+#ifdef DEBUG_VERBOSE
+ {
+ char *hexp, *asciip;
+ asciip = (lastNamep ? lastNamep : pathp);
+ hexp = osi_HexifyString( asciip );
+ DEBUG_EVENT2("AFS","T2Open H[%s] A[%s]", hexp, asciip);
+ free(hexp);
+ }
+#endif
+
userp = smb_GetTran2User(vcp, p);
+ /* In the off chance that userp is NULL, we log and abandon */
+ if(!userp) {
+ osi_Log1(afsd_logp, "ReceiveTran2Open user [%d] not resolvable", p->uid);
+ smb_FreeTran2Packet(outp);
+ return CM_ERROR_BADSMB;
+ }
+
tidPathp = smb_GetTIDPath(vcp, p->tid);
dscp = NULL;
}
else openAction = 1; /* found existing file */
}
- else if (!(openFun & 0x10)) {
+ else if (!(openFun & SMB_ATTR_DIRECTORY)) {
/* don't create if not found */
if (dscp) cm_ReleaseSCache(dscp);
osi_assert(scp == NULL);
if (extraInfo) {
outp->parmsp[parmSlot] = smb_Attributes(scp); parmSlot++;
smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
- outp->parmsp[parmSlot] = dosTime & 0xffff; parmSlot++;
- outp->parmsp[parmSlot] = (dosTime>>16) & 0xffff; parmSlot++;
+ outp->parmsp[parmSlot] = (unsigned short)(dosTime & 0xffff); parmSlot++;
+ outp->parmsp[parmSlot] = (unsigned short)((dosTime>>16) & 0xffff); parmSlot++;
outp->parmsp[parmSlot] = (unsigned short) (scp->length.LowPart & 0xffff);
parmSlot++;
outp->parmsp[parmSlot] = (unsigned short) ((scp->length.LowPart >> 16) & 0xffff);
case 2:
/* volume info */
- qi.u.volumeInfo.vsn = 1234;
- qi.u.volumeInfo.vnCount = 4;
+ qi.u.volumeInfo.vsn = 1234;
+ qi.u.volumeInfo.vnCount = 4;
/* we're supposed to pad it out with zeroes to the end */
memset(&qi.u.volumeInfo.label, 0, sizeof(qi.u.volumeInfo.label));
- strcpy(qi.u.volumeInfo.label, "AFS");
+ memcpy(qi.u.volumeInfo.label, "AFS", 4);
break;
case 0x102:
/* FS volume info */
memset((char *)&qi.u.FSvolumeInfo.vct, 0, sizeof(FILETIME));
qi.u.FSvolumeInfo.vsn = 1234;
- qi.u.FSvolumeInfo.vnCount = 4;
- strcpy(qi.u.FSvolumeInfo.label, "AFS");
+ qi.u.FSvolumeInfo.vnCount = 8;
+ memcpy(qi.u.FSvolumeInfo.label, "A\0F\0S\0\0", 8);
break;
case 0x103:
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;
}
userp = smb_GetTran2User(vcp, p);
+ if(!userp) {
+ osi_Log1(afsd_logp, "ReceiveTran2QPathInfo unable to resolve user [%d]", p->uid);
+ smb_FreeTran2Packet(outp);
+ return CM_ERROR_BADSMB;
+ }
tidPathp = smb_GetTIDPath(vcp, p->tid);
spacep = cm_GetSpace();
smb_StripLastComponent(spacep->data, &lastComp,
(char *)(&p->parmsp[3]));
- if (strcmp(lastComp, "\\desktop.ini") == 0) {
- code = cm_NameI(cm_rootSCachep, spacep->data,
- CM_FLAG_CASEFOLD
- | CM_FLAG_DIRSEARCH
- | CM_FLAG_FOLLOW,
- userp, tidPathp, &req, &dscp);
- if (code == 0) {
- if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT
- && !dscp->mountRootFidp)
- code = CM_ERROR_NOSUCHFILE;
- else if (dscp->fileType == CM_SCACHETYPE_DIRECTORY) {
- cm_buf_t *bp = buf_Find(dscp, &hzero);
- if (bp)
- buf_Release(bp);
- else
- code = CM_ERROR_NOSUCHFILE;
- }
- cm_ReleaseSCache(dscp);
- if (code) {
- cm_FreeSpace(spacep);
- cm_ReleaseUser(userp);
- smb_SendTran2Error(vcp, p, opx, code);
- smb_FreeTran2Packet(outp);
- return 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
+ | CM_FLAG_FOLLOW,
+ userp, tidPathp, &req, &dscp);
+ if (code == 0) {
+ if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT
+ && !dscp->mountRootFidp)
+ code = CM_ERROR_NOSUCHFILE;
+ else if (dscp->fileType == CM_SCACHETYPE_DIRECTORY) {
+ cm_buf_t *bp = buf_Find(dscp, &hzero);
+ if (bp)
+ buf_Release(bp);
+ else
+ code = CM_ERROR_NOSUCHFILE;
+ }
+ cm_ReleaseSCache(dscp);
+ if (code) {
+ cm_FreeSpace(spacep);
+ cm_ReleaseUser(userp);
+ smb_SendTran2Error(vcp, p, opx, code);
+ smb_FreeTran2Packet(outp);
+ return 0;
+ }
+ }
+ }
+ }
cm_FreeSpace(spacep);
}
smb_FreeTran2Packet(outp);
return 0;
}
-
+
lock_ObtainMutex(&scp->mx);
code = cm_SyncOp(scp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
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;
}
outp->totalData = nbytesRequired;
userp = smb_GetTran2User(vcp, p);
+ if(!userp) {
+ osi_Log1(afsd_logp, "ReceiveTran2QFileInfo unable to resolve user [%d]", p->uid);
+ code = CM_ERROR_BADSMB;
+ goto done;
+ }
scp = fidp->scp;
lock_ObtainMutex(&scp->mx);
*((LARGE_INTEGER *)op) = scp->length; op += 8; /* EOF */
*((u_long *)op) = scp->linkCount; op += 4;
*op++ = ((fidp->flags & SMB_FID_DELONCLOSE) ? 1 : 0);
- *op++ = 0;
*op++ = (scp->fileType == CM_SCACHETYPE_DIRECTORY ? 1 : 0);
*op++ = 0;
+ *op++ = 0;
}
else if (infoLevel == 0x103) {
*((u_long *)op) = 0; op += 4;
outp->totalData = 0;
userp = smb_GetTran2User(vcp, p);
+ if(!userp) {
+ osi_Log1(afsd_logp,"ReceiveTran2SetFileInfo unable to resolve user [%d]", p->uid);
+ code = CM_ERROR_BADSMB;
+ goto done;
+ }
scp = fidp->scp;
/* 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)
/* Copy attributes */
lattr = smb_ExtAttributes(scp);
+ /* merge in hidden (dot file) attribute */
+ if( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
+ lattr |= SMB_ATTR_HIDDEN;
*((u_long *)dptr) = lattr;
dptr += 4;
}
/* finally copy out attributes as short */
attr = smb_Attributes(scp);
+ /* merge in hidden (dot file) attribute */
+ if( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
+ attr |= SMB_ATTR_HIDDEN;
*dptr++ = attr & 0xff;
*dptr++ = (attr >> 8) & 0xff;
}
char shortName[13]; /* 8.3 name if needed */
int NeedShortName;
char *shortNameEnd;
+ int fileType;
+ cm_fid_t fid;
cm_req_t req;
osi_LogSaveString(afsd_logp, pathp));
/* bail out if request looks bad */
- if (p->opcode == 1 && !pathp) {
- return CM_ERROR_BADSMB;
- }
+ if (p->opcode == 1 && !pathp) {
+ smb_ReleaseDirSearch(dsp);
+ smb_FreeTran2Packet(outp);
+ return CM_ERROR_BADSMB;
+ }
osi_Log2(afsd_logp, "T2 dir search cookie 0x%x, connection %d",
nextCookie, dsp->cookie);
- userp = smb_GetTran2User(vcp, p);
+ userp = smb_GetTran2User(vcp, p);
+ if (!userp) {
+ osi_Log1(afsd_logp, "T2 dir search unable to resolve user [%d]", p->uid);
+ smb_ReleaseDirSearch(dsp);
+ smb_FreeTran2Packet(outp);
+ return CM_ERROR_BADSMB;
+ }
/* try to get the vnode for the path name next */
lock_ObtainMutex(&dsp->mx);
curOffset.LowPart &= ~(2048-1);
curOffset.LowPart |= temp;
- /* check if we've returned all the names that will fit in the
- * response packet; we check return count as well as the number
- * of bytes requested. We check the # of bytes after we find
- * the dir entry, since we'll need to check its size.
- */
- if (returnedNames >= maxCount) break;
+ /* check if we've passed the dir's EOF */
+ if (LargeIntegerGreaterThanOrEqualTo(curOffset, dirLength)) {
+ eos = 1;
+ break;
+ }
+
+ /* check if we've returned all the names that will fit in the
+ * response packet; we check return count as well as the number
+ * of bytes requested. We check the # of bytes after we find
+ * the dir entry, since we'll need to check its size.
+ */
+ if (returnedNames >= maxCount) {
+ break;
+ }
- /* check if we've passed the dir's EOF */
- if (LargeIntegerGreaterThanOrEqualTo(curOffset, dirLength)) {
- eos = 1;
- break;
- }
-
- /* see if we can use the bufferp we have now; compute in which
- * page the current offset would be, and check whether that's
- * the offset of the buffer we have. If not, get the buffer.
- */
- thyper.HighPart = curOffset.HighPart;
- thyper.LowPart = curOffset.LowPart & ~(buf_bufferSize-1);
- if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
+ /* see if we can use the bufferp we have now; compute in which
+ * page the current offset would be, and check whether that's
+ * the offset of the buffer we have. If not, get the buffer.
+ */
+ thyper.HighPart = curOffset.HighPart;
+ thyper.LowPart = curOffset.LowPart & ~(buf_bufferSize-1);
+ if (!bufferp || !LargeIntegerEqualTo(thyper, bufferOffset)) {
/* wrong buffer */
- if (bufferp) {
- buf_Release(bufferp);
- bufferp = NULL;
- }
+ if (bufferp) {
+ buf_Release(bufferp);
+ bufferp = NULL;
+ }
lock_ReleaseMutex(&scp->mx);
lock_ObtainRead(&scp->bufCreateLock);
code = buf_Get(scp, &thyper, &bufferp);
|| (NeedShortName
&& smb_V3MatchMask(shortName, maskp,
CM_FLAG_CASEFOLD)))) {
+
+ /* Eliminate entries that don't match requested
+ attributes */
+ if (smb_hideDotFiles && !(dsp->attribute & SMB_ATTR_HIDDEN) &&
+ smb_IsDotFile(dep->name))
+ goto nextEntry; /* no hidden files */
+
+ if (!(dsp->attribute & SMB_ATTR_DIRECTORY)) /* 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 */
curPatchp->dptr = op;
if (infoLevel >= 0x101)
curPatchp->dptr += 8;
+
+ if (smb_hideDotFiles && smb_IsDotFile(dep->name)) {
+ curPatchp->flags = SMB_DIRLISTPATCH_DOTFILE;
+ }
+ else
+ curPatchp->flags = 0;
+
curPatchp->fid.cell = scp->fid.cell;
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)
* or if something went wrong, close the search.
*/
/* ((searchFlags & 1) || ((searchFlags & 2) && eos) */
- if ((searchFlags & 1) || (returnedNames == 0)
- || code != 0) smb_DeleteDirSearch(dsp);
+ if ((searchFlags & 1) || (returnedNames == 0) || ((searchFlags & 2) &&
+ eos) || code != 0)
+ smb_DeleteDirSearch(dsp);
if (code)
smb_SendTran2Error(vcp, p, opx, code);
else {
if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) {
/* special case magic file name for receiving IOCTL requests
- * (since IOCTL calls themselves aren't getting through).
- */
+ * (since IOCTL calls themselves aren't getting through).
+ */
+#ifdef NOTSERVICE
+ osi_Log0(afsd_logp, "IOCTL Open");
+#endif
+
fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE);
smb_SetupIoctlFid(fidp, spacep);
return 0;
}
- userp = smb_GetUser(vcp, inp);
+#ifdef DEBUG_VERBOSE
+ {
+ char *hexp, *asciip;
+ asciip = (lastNamep ? lastNamep : pathp );
+ hexp = osi_HexifyString(asciip);
+ DEBUG_EVENT2("AFS", "V3Open H[%s] A[%s]", hexp, asciip );
+ free(hexp);
+ }
+#endif
+ userp = smb_GetUser(vcp, inp);
dscp = NULL;
tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
if (searchTime != 0) {
smb_UnixTimeFromSearchTime(&unixTime, searchTime);
+
+ if ( unixTime != -1 ) {
attrs.mask = CM_ATTRMASK_CLIENTMODTIME;
attrs.clientModTime = unixTime;
code = cm_SetAttr(scp, &attrs, userp, &req);
+
+ osi_Log1(afsd_logp, "SMB receive V3SetAttributes [fid=%ld]", fid);
+ } else {
+ osi_Log1(afsd_logp, "**smb_UnixTimeFromSearchTime failed searchTime=%ld", searchTime);
+ }
}
else code = 0;
/* 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);
cm_scache_t *scp; /* file to create or open */
cm_attr_t setAttr;
char *lastNamep;
+ char *treeStartp;
unsigned short nameLength;
unsigned int flags;
unsigned int requestOpLock;
unsigned int requestBatchOpLock;
unsigned int mustBeDir;
+ unsigned int treeCreate;
int realDirFlag;
unsigned int desiredAccess;
unsigned int extAttributes;
cm_InitReq(&req);
+ treeCreate = FALSE;
foundscp = FALSE;
scp = NULL;
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &lastNamep, realPathp);
+ osi_Log1(afsd_logp,"NTCreateX for [%s]",osi_LogSaveString(afsd_logp,realPathp));
+ osi_Log4(afsd_logp,"NTCreateX da=[%x] ea=[%x] cd=[%x] co=[%x]", desiredAccess, extAttributes, createDisp, createOptions);
+
if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) {
/* special case magic file name for receiving IOCTL requests
* (since IOCTL calls themselves aren't getting through).
return 0;
}
- userp = smb_GetUser(vcp, inp);
+#ifdef DEBUG_VERBOSE
+ {
+ char *hexp, *asciip;
+ asciip = (lastNamep? lastNamep : realPathp);
+ hexp = osi_HexifyString( asciip );
+ DEBUG_EVENT2("AFS", "NTCreateX H[%s] A[%s]", hexp, asciip);
+ free(hexp);
+ }
+#endif
+ userp = smb_GetUser(vcp, inp);
+ if (!userp) {
+ osi_Log1(afsd_logp, "NTCreateX Invalid user [%d]", ((smb_t *) inp)->uid);
+ free(realPathp);
+ return CM_ERROR_INVAL;
+ }
if (baseFid == 0) {
baseDirp = cm_rootSCachep;
tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
}
else {
- baseFidp = smb_FindFID(vcp, baseFid, 0);
+ baseFidp = smb_FindFID(vcp, baseFid, 0);
+ if (!baseFidp) {
+ osi_Log1(afsd_logp, "NTCreateX Invalid base fid [%d]", baseFid);
+ free(realPathp);
+ cm_ReleaseUser(userp);
+ return CM_ERROR_INVAL;
+ }
baseDirp = baseFidp->scp;
tidPathp = NULL;
}
- /* compute open mode */
+ osi_Log1(afsd_logp, "NTCreateX tidPathp=[%s]", (tidPathp==NULL)?"null": osi_LogSaveString(afsd_logp,tidPathp));
+
+ /* compute open mode */
fidflags = 0;
if (desiredAccess & DELETE)
fidflags |= SMB_FID_OPENDELETE;
if (code != 0
|| (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) {
/* look up parent directory */
- code = cm_NameI(baseDirp, spacep->data,
- CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
- userp, tidPathp, &req, &dscp);
+ /* If we are trying to create a path (i.e. multiple nested directories), then we don't *need*
+ the immediate parent. We have to work our way up realPathp until we hit something that we
+ recognize.
+ */
+
+ while(1) {
+ char *tp;
+
+ code = cm_NameI(baseDirp, spacep->data,
+ CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+ userp, tidPathp, &req, &dscp);
+
+ if(code &&
+ (tp = strrchr(spacep->data,'\\')) &&
+ (createDisp == 2) &&
+ (realDirFlag == 1)) {
+ *tp++ = 0;
+ treeCreate = TRUE;
+ treeStartp = realPathp + (tp - spacep->data);
+
+ if(*tp && !smb_IsLegalFilename(tp)) {
+ if(baseFid != 0) smb_ReleaseFID(baseFidp);
+ cm_ReleaseUser(userp);
+ free(realPathp);
+ return CM_ERROR_BADNTFILENAME;
+ }
+ }
+ else
+ break;
+ }
- if (baseFid != 0) smb_ReleaseFID(baseFidp);
+ if (baseFid != 0) smb_ReleaseFID(baseFidp);
- if (code) {
- cm_ReleaseUser(userp);
- free(realPathp);
- return code;
- }
+ if (code) {
+ osi_Log0(afsd_logp,"NTCreateX parent not found");
+ cm_ReleaseUser(userp);
+ free(realPathp);
+ return code;
+ }
- if (!lastNamep) lastNamep = realPathp;
- else lastNamep++;
+ if(treeCreate && dscp->fileType == CM_SCACHETYPE_FILE) {
+ /* A file exists where we want a directory. */
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ free(realPathp);
+ return CM_ERROR_EXISTS;
+ }
- if (!smb_IsLegalFilename(lastNamep))
- return CM_ERROR_BADNTFILENAME;
+ if (!lastNamep) lastNamep = realPathp;
+ else lastNamep++;
- if (!foundscp) {
+ if (!smb_IsLegalFilename(lastNamep)) {
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseUser(userp);
+ free(realPathp);
+ return CM_ERROR_BADNTFILENAME;
+ }
+
+ if (!foundscp && !treeCreate) {
code = cm_Lookup(dscp, lastNamep,
CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
userp, &req, &scp);
* by dscp, or we may have found the file directly. If code is non-zero,
* scp is NULL.
*/
- if (code == 0) {
+ if (code == 0 && !treeCreate) {
code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp,
&req);
if (code) {
}
}
else {
- /* create directory */
- osi_assert(dscp != NULL);
- osi_Log1(afsd_logp, "smb_ReceiveNTCreateX creating directory %s",
- osi_LogSaveString(afsd_logp, lastNamep));
+ char *tp, *pp;
+ char *cp; /* This component */
+ int clen; /* length of component */
+ cm_scache_t *tscp;
+ int isLast = 0;
+
+ /* create directory */
+ if ( !treeCreate ) treeStartp = lastNamep;
+ osi_assert(dscp != NULL);
+ osi_Log1(afsd_logp, "smb_ReceiveNTCreateX creating directory [%s]",
+ osi_LogSaveString(afsd_logp, treeStartp));
openAction = 2; /* created directory */
+
setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
setAttr.clientModTime = time(NULL);
- code = cm_MakeDir(dscp, lastNamep, 0, &setAttr, userp, &req);
- if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
- smb_NotifyChange(FILE_ACTION_ADDED,
- FILE_NOTIFY_CHANGE_DIR_NAME,
- dscp, lastNamep, NULL, TRUE);
- if (code == 0
- || (code == CM_ERROR_EXISTS && createDisp != 2)) {
- /* Not an exclusive create, and someone else tried
- * creating it already, then we open it anyway. We
- * don't bother retrying after this, since if this next
- * fails, that means that the file was deleted after we
- * started this call.
- */
- code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
- userp, &req, &scp);
+
+ pp = treeStartp;
+ cp = spacep->data;
+ tscp = dscp;
+
+ while(pp && *pp) {
+ tp = strchr(pp, '\\');
+ if(!tp) {
+ strcpy(cp,pp);
+ isLast = 1; /* indicate last component. the supplied path never ends in a slash */
+ }
+ else {
+ clen = tp - pp;
+ strncpy(cp,pp,clen);
+ *(cp + clen) = 0;
+ tp++;
+ }
+ pp = tp;
+
+ if(clen == 0) continue; /* the supplied path can't have consecutive slashes either , but */
+
+ /* cp is the next component to be created. */
+ code = cm_MakeDir(tscp, cp, 0, &setAttr, userp, &req);
+ if (code == 0 && (tscp->flags & CM_SCACHEFLAG_ANYWATCH))
+ smb_NotifyChange(FILE_ACTION_ADDED,
+ FILE_NOTIFY_CHANGE_DIR_NAME,
+ tscp, cp, NULL, TRUE);
+ if (code == 0 ||
+ (code == CM_ERROR_EXISTS && createDisp != 2)) {
+ /* Not an exclusive create, and someone else tried
+ * creating it already, then we open it anyway. We
+ * don't bother retrying after this, since if this next
+ * fails, that means that the file was deleted after we
+ * started this call.
+ */
+ code = cm_Lookup(tscp, cp, CM_FLAG_CASEFOLD,
+ userp, &req, &scp);
+ }
+ if(code) break;
+
+ if(!isLast) { /* for anything other than dscp, release it unless it's the last one */
+ cm_ReleaseSCache(tscp);
+ tscp = scp; /* Newly created directory will be next parent */
+ }
}
+
+ /*
+ if we get here and code == 0, then scp is the last directory created, and tscp is the
+ parent of scp. dscp got released if dscp != tscp. both tscp and scp are held.
+ */
+ dscp = tscp;
}
if (code) {
/* something went wrong creating or truncating the file */
if (scp) cm_ReleaseSCache(scp);
+ if (dscp) cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
return code;
}
- /* make sure we have file vs. dir right */
+ /* make sure we have file vs. dir right (only applies for single component case) */
if (realDirFlag == 0 && scp->fileType != CM_SCACHETYPE_FILE) {
cm_ReleaseSCache(scp);
+ if (dscp) cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
return CM_ERROR_ISDIR;
}
+ /* (only applies to single component case) */
if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) {
cm_ReleaseSCache(scp);
+ if (dscp) cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
free(realPathp);
return CM_ERROR_NOTDIR;
cm_ReleaseUser(userp);
+ /* Can't free realPathp if we get here since fidp->NTopen_wholepathp is pointing there */
+
/* leave scp held since we put it in fidp->scp */
return 0;
}
unsigned int requestOpLock;
unsigned int requestBatchOpLock;
unsigned int mustBeDir;
+ unsigned int extendedRespRequired;
int realDirFlag;
unsigned int desiredAccess;
+#ifdef DEBUG_VERBOSE
+ unsigned int allocSize;
+ unsigned int shareAccess;
+#endif
unsigned int extAttributes;
unsigned int createDisp;
+#ifdef DEBUG_VERBOSE
+ unsigned int sdLen;
+#endif
unsigned int createOptions;
int initialModeBits;
unsigned short baseFid;
requestOpLock = flags & 0x02;
requestBatchOpLock = flags & 0x04;
mustBeDir = flags & 0x08;
+ extendedRespRequired = flags & 0x10;
+
/*
* Why all of a sudden 32-bit FID?
* We will reject all bits higher than 16.
return CM_ERROR_INVAL;
baseFid = (unsigned short)lparmp[1];
desiredAccess = lparmp[2];
+#ifdef DEBUG_VERBOSE
+ allocSize = lparmp[3];
+#endif /* DEBUG_VERSOSE */
extAttributes = lparmp[5];
+#ifdef DEBUG_VEROSE
+ shareAccess = lparmp[6];
+#endif
createDisp = lparmp[7];
createOptions = lparmp[8];
+#ifdef DEBUG_VERBOSE
+ sdLen = lparmp[9];
+#endif
nameLength = lparmp[11];
+#ifdef DEBUG_VERBOSE
+ osi_Log4(afsd_logp,"NTTransCreate with da[%x],ea[%x],sa[%x],cd[%x]",desiredAccess,extAttributes,shareAccess,createDisp);
+ osi_Log2(afsd_logp,"... co[%x],sdl[%x],as[%x]",createOptions,sdLen,allocSize);
+ osi_Log1(afsd_logp,"... flags[%x]",flags);
+#endif
+
/* mustBeDir is never set; createOptions directory bit seems to be
* more important
*/
* Will add it if necessary.
*/
+#ifdef DEBUG_VERBOSE
+ {
+ char *hexp, *asciip;
+ asciip = (lastNamep? lastNamep : realPathp);
+ hexp = osi_HexifyString( asciip );
+ DEBUG_EVENT2("AFS", "NTTranCreate H[%s] A[%s]", hexp, asciip);
+ free(hexp);
+ }
+#endif
+
userp = smb_GetUser(vcp, inp);
+ if(!userp) {
+ osi_Log1(afsd_logp, "NTTranCreate invalid user [%d]", ((smb_t *) inp)->uid);
+ free(realPathp);
+ return CM_ERROR_INVAL;
+ }
if (baseFid == 0) {
baseDirp = cm_rootSCachep;
tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid);
}
else {
- baseFidp = smb_FindFID(vcp, baseFid, 0);
+ baseFidp = smb_FindFID(vcp, baseFid, 0);
+ if(!baseFidp) {
+ osi_Log1(afsd_logp, "NTTranCreate Invalid fid [%d]", baseFid);
+ free(realPathp);
+ cm_ReleaseUser(userp);
+ return CM_ERROR_INVAL;
+ }
baseDirp = baseFidp->scp;
tidPathp = NULL;
}
/* set inp->fid so that later read calls in same msg can find fid */
inp->fid = fidp->fid;
- /* out parms */
- parmOffset = 8*4 + 39;
- parmOffset += 1; /* pad to 4 */
- dataOffset = parmOffset + 70;
-
- parmSlot = 1;
- outp->oddByte = 1;
- /* Total Parameter Count */
- smb_SetSMBParmLong(outp, parmSlot, 70); parmSlot += 2;
- /* Total Data Count */
- smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
- /* Parameter Count */
- smb_SetSMBParmLong(outp, parmSlot, 70); parmSlot += 2;
- /* Parameter Offset */
- smb_SetSMBParmLong(outp, parmSlot, parmOffset); parmSlot += 2;
- /* Parameter Displacement */
- smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
- /* Data Count */
- smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
- /* Data Offset */
- smb_SetSMBParmLong(outp, parmSlot, dataOffset); parmSlot += 2;
- /* Data Displacement */
- smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
- smb_SetSMBParmByte(outp, parmSlot, 0); /* Setup Count */
- smb_SetSMBDataLength(outp, 70);
+ /* check whether we are required to send an extended response */
+ if (!extendedRespRequired) {
+ /* out parms */
+ parmOffset = 8*4 + 39;
+ parmOffset += 1; /* pad to 4 */
+ dataOffset = parmOffset + 70;
+
+ parmSlot = 1;
+ outp->oddByte = 1;
+ /* Total Parameter Count */
+ smb_SetSMBParmLong(outp, parmSlot, 70); parmSlot += 2;
+ /* Total Data Count */
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ /* Parameter Count */
+ smb_SetSMBParmLong(outp, parmSlot, 70); parmSlot += 2;
+ /* Parameter Offset */
+ smb_SetSMBParmLong(outp, parmSlot, parmOffset); parmSlot += 2;
+ /* Parameter Displacement */
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ /* Data Count */
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ /* Data Offset */
+ smb_SetSMBParmLong(outp, parmSlot, dataOffset); parmSlot += 2;
+ /* Data Displacement */
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ smb_SetSMBParmByte(outp, parmSlot, 0); /* Setup Count */
+ smb_SetSMBDataLength(outp, 70);
- lock_ObtainMutex(&scp->mx);
- outData = smb_GetSMBData(outp, NULL);
- outData++; /* round to get to parmOffset */
- *outData = 0; outData++; /* oplock */
- *outData = 0; outData++; /* reserved */
- *((USHORT *)outData) = fidp->fid; outData += 2; /* fid */
- *((ULONG *)outData) = openAction; outData += 4;
- *((ULONG *)outData) = 0; outData += 4; /* EA error offset */
- smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
- *((FILETIME *)outData) = ft; outData += 8; /* creation time */
- *((FILETIME *)outData) = ft; outData += 8; /* last access time */
- *((FILETIME *)outData) = ft; outData += 8; /* last write time */
- *((FILETIME *)outData) = ft; outData += 8; /* change time */
- *((ULONG *)outData) = smb_ExtAttributes(scp); outData += 4;
- *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* alloc sz */
- *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* EOF */
- *((USHORT *)outData) = 0; outData += 2; /* filetype */
- *((USHORT *)outData) = 0; outData += 2; /* dev state */
- *((USHORT *)outData) = (scp->fileType == CM_SCACHETYPE_DIRECTORY);
- outData += 2; /* is a dir? */
- lock_ReleaseMutex(&scp->mx);
+ lock_ObtainMutex(&scp->mx);
+ outData = smb_GetSMBData(outp, NULL);
+ outData++; /* round to get to parmOffset */
+ *outData = 0; outData++; /* oplock */
+ *outData = 0; outData++; /* reserved */
+ *((USHORT *)outData) = fidp->fid; outData += 2; /* fid */
+ *((ULONG *)outData) = openAction; outData += 4;
+ *((ULONG *)outData) = 0; outData += 4; /* EA error offset */
+ smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+ *((FILETIME *)outData) = ft; outData += 8; /* creation time */
+ *((FILETIME *)outData) = ft; outData += 8; /* last access time */
+ *((FILETIME *)outData) = ft; outData += 8; /* last write time */
+ *((FILETIME *)outData) = ft; outData += 8; /* change time */
+ *((ULONG *)outData) = smb_ExtAttributes(scp); outData += 4;
+ *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* alloc sz */
+ *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* EOF */
+ *((USHORT *)outData) = 0; outData += 2; /* filetype */
+ *((USHORT *)outData) = 0; outData += 2; /* dev state */
+ *((USHORT *)outData) = (scp->fileType == CM_SCACHETYPE_DIRECTORY);
+ outData += 2; /* is a dir? */
+ lock_ReleaseMutex(&scp->mx);
+ } else {
+ /* out parms */
+ parmOffset = 8*4 + 39;
+ parmOffset += 1; /* pad to 4 */
+ dataOffset = parmOffset + 104;
+
+ parmSlot = 1;
+ outp->oddByte = 1;
+ /* Total Parameter Count */
+ smb_SetSMBParmLong(outp, parmSlot, 101); parmSlot += 2;
+ /* Total Data Count */
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ /* Parameter Count */
+ smb_SetSMBParmLong(outp, parmSlot, 101); parmSlot += 2;
+ /* Parameter Offset */
+ smb_SetSMBParmLong(outp, parmSlot, parmOffset); parmSlot += 2;
+ /* Parameter Displacement */
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ /* Data Count */
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ /* Data Offset */
+ smb_SetSMBParmLong(outp, parmSlot, dataOffset); parmSlot += 2;
+ /* Data Displacement */
+ smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2;
+ smb_SetSMBParmByte(outp, parmSlot, 0); /* Setup Count */
+ smb_SetSMBDataLength(outp, 105);
+
+ lock_ObtainMutex(&scp->mx);
+ outData = smb_GetSMBData(outp, NULL);
+ outData++; /* round to get to parmOffset */
+ *outData = 0; outData++; /* oplock */
+ *outData = 1; outData++; /* response type */
+ *((USHORT *)outData) = fidp->fid; outData += 2; /* fid */
+ *((ULONG *)outData) = openAction; outData += 4;
+ *((ULONG *)outData) = 0; outData += 4; /* EA error offset */
+ smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
+ *((FILETIME *)outData) = ft; outData += 8; /* creation time */
+ *((FILETIME *)outData) = ft; outData += 8; /* last access time */
+ *((FILETIME *)outData) = ft; outData += 8; /* last write time */
+ *((FILETIME *)outData) = ft; outData += 8; /* change time */
+ *((ULONG *)outData) = smb_ExtAttributes(scp); outData += 4;
+ *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* alloc sz */
+ *((LARGE_INTEGER *)outData) = scp->length; outData += 8; /* EOF */
+ *((USHORT *)outData) = 0; outData += 2; /* filetype */
+ *((USHORT *)outData) = 0; outData += 2; /* dev state */
+ *((USHORT *)outData) = (scp->fileType == CM_SCACHETYPE_DIRECTORY);
+ outData += 1; /* is a dir? */
+ memset(outData,0,24); outData += 24; /* Volume ID and file ID */
+ *((ULONG *)outData) = 0x001f01ffL; outData += 4; /* Maxmimal access rights */
+ *((ULONG *)outData) = 0; outData += 4; /* Guest Access rights */
+ lock_ReleaseMutex(&scp->mx);
+ }
osi_Log1(afsd_logp, "SMB NTTranCreate opening fid %d", fidp->fid);
cm_ReleaseUser(userp);
+ /* free(realPathp); Can't free realPathp here because fidp->NTopen_wholepathp points there */
/* leave scp held since we put it in fidp->scp */
return 0;
}
filter = smb_GetSMBParm(inp, 19)
| (smb_GetSMBParm(inp, 20) << 16);
fid = smb_GetSMBParm(inp, 21);
- watchtree = smb_GetSMBParm(inp, 22) && 0xffff;
+ watchtree = smb_GetSMBParm(inp, 22) && 0xffff; /* TODO: should this be 0xff ? */
+
+ fidp = smb_FindFID(vcp, fid, 0);
+ if (!fidp) {
+ osi_Log1(afsd_logp, "ERROR: NotifyChange given invalid fid [%d]", fid);
+ return CM_ERROR_BADFD;
+ }
savedPacketp = smb_CopyPacket(inp);
- savedPacketp->vcp = vcp;
+ savedPacketp->vcp = vcp; /* TODO: refcount vcp? */
lock_ObtainMutex(&smb_Dir_Watch_Lock);
savedPacketp->nextp = smb_Directory_Watches;
smb_Directory_Watches = savedPacketp;
fidp = smb_FindFID(vcp, fid, 0);
- osi_Log4(afsd_logp, "Request for NotifyChange filter 0x%x fid %d wtree %d file %s",
- filter, fid, watchtree, osi_LogSaveString(afsd_logp, fidp->NTopen_wholepathp));
+ if (fidp) {
+ osi_Log4(afsd_logp, "Request for NotifyChange filter 0x%x fid %d wtree %d file %s",
+ filter, fid, watchtree, osi_LogSaveString(afsd_logp, fidp->NTopen_wholepathp));
- scp = fidp->scp;
- lock_ObtainMutex(&scp->mx);
- if (watchtree)
- scp->flags |= CM_SCACHEFLAG_WATCHEDSUBTREE;
- else
- scp->flags |= CM_SCACHEFLAG_WATCHED;
- lock_ReleaseMutex(&scp->mx);
- smb_ReleaseFID(fidp);
+ scp = fidp->scp;
+ lock_ObtainMutex(&scp->mx);
+ if (watchtree)
+ scp->flags |= CM_SCACHEFLAG_WATCHEDSUBTREE;
+ else
+ scp->flags |= CM_SCACHEFLAG_WATCHED;
+ lock_ReleaseMutex(&scp->mx);
+ smb_ReleaseFID(fidp);
+ }
+ else
+ {
+ /* nothing - just a warning to main log file ... */
+ afsi_log("Warning: cannot find fidp vcp = 0x%X, fid = %d", vcp, fid);
+ }
outp->flags |= SMB_PACKETFLAG_NOSEND;
filter = smb_GetSMBParm(watch, 19)
| (smb_GetSMBParm(watch, 20) << 16);
fid = smb_GetSMBParm(watch, 21);
- wtree = smb_GetSMBParm(watch, 22) & 0xffff;
+ wtree = smb_GetSMBParm(watch, 22) & 0xffff; /* TODO: should this be 0xff ? */
maxLen = smb_GetSMBOffsetParm(watch, 5, 1)
| (smb_GetSMBOffsetParm(watch, 6, 1) << 16);
vcp = watch->vcp;
filter = 0x17;
fidp = smb_FindFID(vcp, fid, 0);
+ if (!fidp) {
+ lastWatch = watch;
+ watch = watch->nextp;
+ continue;
+ }
if (fidp->scp != dscp
|| (filter & notifyFilter) == 0
|| (!isDirectParent && !wtree)) {
watchtree = smb_GetSMBParm(watch, 22) & 0xffff;
fidp = smb_FindFID(vcp, fid, 0);
-
- osi_Log3(afsd_logp, "Cancelling change notification for fid %d wtree %d file %s",
- fid, watchtree,
- osi_LogSaveString(afsd_logp, fidp->NTopen_wholepathp));
-
- scp = fidp->scp;
- lock_ObtainMutex(&scp->mx);
- if (watchtree)
- scp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
- else
- scp->flags &= ~CM_SCACHEFLAG_WATCHED;
- lock_ReleaseMutex(&scp->mx);
- smb_ReleaseFID(fidp);
+ if (fidp) {
+ osi_Log3(afsd_logp, "Cancelling change notification for fid %d wtree %d file %s",
+ fid, watchtree,
+ osi_LogSaveString(afsd_logp, (fidp)?fidp->NTopen_wholepathp:""));
+
+ scp = fidp->scp;
+ lock_ObtainMutex(&scp->mx);
+ if (watchtree)
+ scp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
+ else
+ scp->flags &= ~CM_SCACHEFLAG_WATCHED;
+ lock_ReleaseMutex(&scp->mx);
+ smb_ReleaseFID(fidp);
+ } else {
+ osi_Log2(afsd_logp,"NTCancel unable to resolve fid [%d] in vcp[%x]", fid,vcp);
+ }
/* assume STATUS32; return 0xC0000120 (CANCELED) */
replyWctp = watch->wctp;
{
lock_InitializeMutex(&smb_Dir_Watch_Lock, "Directory Watch List Lock");
}
+
+cm_user_t *smb_FindCMUserByName(/*smb_vc_t *vcp,*/ char *usern, char *machine)
+{
+ /*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;
+}
+