{
const char * s;
switch ( code ) {
- case 0x01: s = "llegal buffer length"; break;
- case 0x03: s = "illegal command"; break;
- case 0x05: s = "command timed out"; break;
- case 0x06: s = "message incomplete, issue another command"; break;
- case 0x07: s = "illegal buffer address"; break;
- case 0x08: s = "session number out of range"; break;
- case 0x09: s = "no resource available"; break;
- case 0x0a: s = "session closed"; break;
- case 0x0b: s = "command cancelled"; break;
- case 0x0d: s = "duplicate name"; break;
- case 0x0e: s = "name table full"; break;
- case 0x0f: s = "no deletions, name has active sessions"; break;
- case 0x11: s = "local session table full"; break;
- case 0x12: s = "remote session table full"; break;
- case 0x13: s = "illegal name number"; break;
- case 0x14: s = "no callname"; break;
- case 0x15: s = "cannot put * in NCB_NAME"; break;
- case 0x16: s = "name in use on remote adapter"; break;
- case 0x17: s = "name deleted"; break;
- case 0x18: s = "session ended abnormally"; break;
- case 0x19: s = "name conflict detected"; break;
- case 0x21: s = "interface busy, IRET before retrying"; break;
- case 0x22: s = "too many commands outstanding, retry later";break;
- case 0x23: s = "ncb_lana_num field invalid"; break;
- case 0x24: s = "command completed while cancel occurring "; break;
- case 0x26: s = "command not valid to cancel"; break;
- case 0x30: s = "name defined by anther local process"; break;
- case 0x34: s = "environment undefined. RESET required"; break;
- case 0x35: s = "required OS resources exhausted"; break;
- case 0x36: s = "max number of applications exceeded"; break;
- case 0x37: s = "no saps available for netbios"; break;
- case 0x38: s = "requested resources are not available"; break;
- case 0x39: s = "invalid ncb address or length > segment"; break;
- case 0x3B: s = "invalid NCB DDID"; break;
- case 0x3C: s = "lock of user area failed"; break;
- case 0x3f: s = "NETBIOS not loaded"; break;
- case 0x40: s = "system error"; break;
+ case 0x01: s = "NRC_BUFLEN llegal buffer length"; break;
+ case 0x03: s = "NRC_ILLCMD illegal command"; break;
+ case 0x05: s = "NRC_CMDTMO command timed out"; break;
+ case 0x06: s = "NRC_INCOMP message incomplete, issue another command"; break;
+ case 0x07: s = "NRC_BADDR illegal buffer address"; break;
+ case 0x08: s = "NRC_SNUMOUT session number out of range"; break;
+ case 0x09: s = "NRC_NORES no resource available"; break;
+ case 0x0a: s = "NRC_SCLOSED asession closed"; break;
+ case 0x0b: s = "NRC_CMDCAN command cancelled"; break;
+ case 0x0d: s = "NRC_DUPNAME duplicate name"; break;
+ case 0x0e: s = "NRC_NAMTFUL name table full"; break;
+ case 0x0f: s = "NRC_ACTSES no deletions, name has active sessions"; break;
+ case 0x11: s = "NRC_LOCTFUL local session table full"; break;
+ case 0x12: s = "NRC_REMTFUL remote session table full"; break;
+ case 0x13: s = "NRC_ILLNN illegal name number"; break;
+ case 0x14: s = "NRC_NOCALL no callname"; break;
+ case 0x15: s = "NRC_NOWILD cannot put * in NCB_NAME"; break;
+ case 0x16: s = "NRC_INUSE name in use on remote adapter"; break;
+ case 0x17: s = "NRC_NAMERR name deleted"; break;
+ case 0x18: s = "NRC_SABORT session ended abnormally"; break;
+ case 0x19: s = "NRC_NAMCONF name conflict detected"; break;
+ case 0x21: s = "NRC_IFBUSY interface busy, IRET before retrying"; break;
+ case 0x22: s = "NRC_TOOMANY too many commands outstanding, retry later";break;
+ case 0x23: s = "NRC_BRIDGE ncb_lana_num field invalid"; break;
+ case 0x24: s = "NRC_CANOCCR command completed while cancel occurring "; break;
+ case 0x26: s = "NRC_CANCEL command not valid to cancel"; break;
+ case 0x30: s = "NRC_DUPENV name defined by anther local process"; break;
+ case 0x34: s = "NRC_ENVNOTDEF xenvironment undefined. RESET required"; break;
+ case 0x35: s = "NRC_OSRESNOTAV required OS resources exhausted"; break;
+ case 0x36: s = "NRC_MAXAPPS max number of applications exceeded"; break;
+ case 0x37: s = "NRC_NOSAPS no saps available for netbios"; break;
+ case 0x38: s = "NRC_NORESOURCES requested resources are not available"; break;
+ case 0x39: s = "NRC_INVADDRESS invalid ncb address or length > segment"; break;
+ case 0x3B: s = "NRC_INVDDID invalid NCB DDID"; break;
+ case 0x3C: s = "NRC_LOCKFAILlock of user area failed"; break;
+ case 0x3f: s = "NRC_OPENERR NETBIOS not loaded"; break;
+ case 0x40: s = "NRC_SYSTEM system error"; break;
default: s = "unknown error";
}
return s;
if (ntsEx == STATUS_SUCCESS) {
memcpy(vcp->encKey, lsaResp->ChallengeToClient, MSV1_0_CHALLENGE_LENGTH);
- LsaFreeReturnBuffer(lsaResp);
} else {
/*
* This will cause the subsequent authentication to fail but
*/
memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
}
+ if (lsaResp)
+ LsaFreeReturnBuffer(lsaResp);
}
else
memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
return vcp;
}
-int smb_IsStarMask(clientchar_t *maskp)
+static int smb_Is8Dot3StarMask(clientchar_t *maskp)
{
int i;
clientchar_t tc;
return 0;
}
+static int smb_IsStarMask(clientchar_t *maskp)
+{
+ int i;
+ clientchar_t tc;
+
+ while (*maskp) {
+ tc = *maskp++;
+ if (tc == _C('?') || tc == _C('*') || tc == _C('>'))
+ return 1;
+ }
+ return 0;
+}
+
#ifdef DEBUG_SMB_REFCOUNT
void smb_ReleaseVCInternalDbg(smb_vc_t *vcp, char * file, long line)
#define smb_ReleaseVCInternal(a) smb_ReleaseVCInternalDbg(a, file, line)
smb_findShare_rock_t * vrock = (smb_findShare_rock_t *) rockp;
normchar_t normName[MAX_PATH];
- cm_FsStringToNormString(dep->name, -1, normName, sizeof(normName)/sizeof(normName[0]));
+ if (cm_FsStringToNormString(dep->name, -1, normName, sizeof(normName)/sizeof(normName[0])) == 0) {
+ osi_Log1(smb_logp, "Skipping entry [%s]. Can't normalize FS string",
+ osi_LogSaveString(smb_logp, dep->name));
+ return 0;
+ }
if (!cm_ClientStrCmpNI(normName, vrock->shareName, 12)) {
if(!cm_ClientStrCmpI(normName, vrock->shareName))
matchType = SMB_FINDSHARE_EXACT_MATCH;
else
matchType = SMB_FINDSHARE_PARTIAL_MATCH;
- if(vrock->match) free(vrock->match);
+ if(vrock->match)
+ free(vrock->match);
vrock->match = cm_FsStringToClientStringAlloc(dep->name, -1, NULL);
vrock->matchType = matchType;
thyper.LowPart = 0;
vrock.shareName = cm_ClientStringToNormStringAlloc(shareName, -1, NULL);
+ if (vrock.shareName == NULL)
+ return 0;
vrock.match = NULL;
vrock.matchType = 0;
if (code == 0) {
clientchar_t temp[1024];
- cm_FsStringToClientString(ftemp, (int)cm_FsStrLen(ftemp), temp, 1024);
+ if (cm_FsStringToClientString(ftemp, -1, temp, 1024) != 0) {
cm_ClientStrPrintfN(pathName, (int)lengthof(pathName),
rw ? _C("/.%S/") : _C("/%S/"), temp);
*pathNamep = cm_ClientStrDup(cm_ClientStrLwr(pathName));
return 1;
}
}
+ }
/* failure */
*pathNamep = NULL;
return 0;
if (!smb_lastDirSearchp)
smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
}
- lock_ObtainMutex(&dsp->mx);
dsp->refCount++;
- lock_ReleaseMutex(&dsp->mx);
break;
}
}
void smb_DeleteDirSearch(smb_dirSearch_t *dsp)
{
- lock_ObtainWrite(&smb_globalLock);
lock_ObtainMutex(&dsp->mx);
osi_Log3(smb_logp,"smb_DeleteDirSearch cookie %d dsp 0x%p scp 0x%p",
dsp->cookie, dsp, dsp->scp);
lock_ReleaseWrite(&dsp->scp->rw);
}
lock_ReleaseMutex(&dsp->mx);
- lock_ReleaseWrite(&smb_globalLock);
}
/* Must be called with the smb_globalLock held */
{
cm_scache_t *scp = NULL;
- lock_ObtainMutex(&dsp->mx);
osi_assertx(dsp->refCount-- > 0, "cm_scache_t refCount 0");
- if (dsp->refCount == 0 && (dsp->flags & SMB_DIRSEARCH_DELETE)) {
- if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp)
- smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q);
- osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
- lock_ReleaseMutex(&dsp->mx);
- lock_FinalizeMutex(&dsp->mx);
- scp = dsp->scp;
- osi_Log3(smb_logp,"smb_ReleaseDirSearch cookie %d dsp 0x%p scp 0x%p",
- dsp->cookie, dsp, scp);
- free(dsp);
- } else {
- lock_ReleaseMutex(&dsp->mx);
+ if (dsp->refCount == 0) {
+ lock_ObtainMutex(&dsp->mx);
+ if (dsp->flags & SMB_DIRSEARCH_DELETE) {
+ if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp)
+ smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q);
+ osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
+ lock_ReleaseMutex(&dsp->mx);
+ lock_FinalizeMutex(&dsp->mx);
+ scp = dsp->scp;
+ osi_Log3(smb_logp,"smb_ReleaseDirSearch cookie %d dsp 0x%p scp 0x%p",
+ dsp->cookie, dsp, scp);
+ free(dsp);
+ } else {
+ lock_ReleaseMutex(&dsp->mx);
+ }
}
/* do this now to avoid spurious locking hierarchy creation */
if (scp)
void smb_GCDirSearches(int isV3)
{
smb_dirSearch_t *prevp;
- smb_dirSearch_t *tp;
+ smb_dirSearch_t *dsp;
smb_dirSearch_t *victimsp[SMB_DIRSEARCH_GCMAX];
int victimCount;
int i;
victimCount = 0; /* how many have we got so far */
- for (tp = smb_lastDirSearchp; tp; tp=prevp) {
+ for (dsp = smb_lastDirSearchp; dsp; dsp=prevp) {
/* we'll move tp from queue, so
* do this early.
*/
- prevp = (smb_dirSearch_t *) osi_QPrev(&tp->q);
+ prevp = (smb_dirSearch_t *) osi_QPrev(&dsp->q);
/* if no one is using this guy, and we're either in the new protocol,
* or we're in the old one and this is a small enough ID to be useful
* to the old protocol, GC this guy.
*/
- if (tp->refCount == 0 && (isV3 || tp->cookie <= 255)) {
+ if (dsp->refCount == 0 && (isV3 || dsp->cookie <= 255)) {
/* hold and delete */
- lock_ObtainMutex(&tp->mx);
- tp->flags |= SMB_DIRSEARCH_DELETE;
- lock_ReleaseMutex(&tp->mx);
- victimsp[victimCount++] = tp;
- tp->refCount++;
+ lock_ObtainMutex(&dsp->mx);
+ dsp->flags |= SMB_DIRSEARCH_DELETE;
+ lock_ReleaseMutex(&dsp->mx);
+ victimsp[victimCount++] = dsp;
+ dsp->refCount++;
}
/* don't do more than this */
/* don't need to watch for refcount zero and deleted, since
* we haven't dropped the global lock.
*/
- lock_ObtainMutex(&dsp->mx);
dsp->refCount--;
- lock_ReleaseMutex(&dsp->mx);
++smb_dirSearchCounter;
continue;
}
char **chainpp, int flags)
{
size_t cb;
+ afs_uint32 type = *inp++;
- if (*inp++ != 0x4)
- return NULL;
+ /*
+ * The first byte specifies the type of the input string.
+ * CIFS TR 1.0 3.2.10. This function only parses null terminated
+ * strings.
+ */
+ switch (type) {
+ /* Length Counted */
+ case 0x1: /* Data Block */
+ case 0x5: /* Variable Block */
+ cb = *inp++ << 16 | *inp++;
+ break;
+
+ /* Null-terminated string */
+ case 0x4: /* ASCII */
+ case 0x3: /* Pathname */
+ case 0x2: /* Dialect */
+ cb = sizeof(pktp->data) - (inp - pktp->data);
+ if (inp < pktp->data || inp >= pktp->data + sizeof(pktp->data)) {
+#ifdef DEBUG_UNICODE
+ DebugBreak();
+#endif
+ cb = sizeof(pktp->data);
+ }
+ break;
+
+ default:
+ return NULL; /* invalid input */
+ }
#ifdef SMB_UNICODE
- if (!WANTS_UNICODE(pktp))
+ if (type == 0x2 /* Dialect */ || !WANTS_UNICODE(pktp))
flags |= SMB_STRF_FORCEASCII;
#endif
- cb = sizeof(pktp->data) - (inp - pktp->data);
- if (inp < pktp->data || inp >= pktp->data + sizeof(pktp->data)) {
-#ifdef DEBUG_UNICODE
- DebugBreak();
-#endif
- cb = sizeof(pktp->data);
- }
return smb_ParseStringBuf(pktp->data, &pktp->stringsp, inp, &cb, chainpp, flags);
}
/* 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) {
+ if (code == 0) {
+ NTStatus = 0;
+ }
+ else if (code == CM_ERROR_NOSUCHCELL) {
NTStatus = 0xC000000FL; /* No such file */
}
else if (code == CM_ERROR_NOSUCHVOLUME) {
NTStatus = 0xC0000033L; /* Object name invalid */
}
else if (code == CM_ERROR_WOULDBLOCK) {
- NTStatus = 0xC0000055L; /* Lock not granted */
+ NTStatus = 0xC00000D8L; /* Can't wait */
}
else if (code == CM_ERROR_SHARING_VIOLATION) {
NTStatus = 0xC0000043L; /* Sharing violation */
}
else if (code == CM_ERROR_LOCK_NOT_GRANTED) {
NTStatus = 0xC0000055L; /* Lock Not Granted */
+ } else if (code == ENOMEM) {
+ NTStatus = 0xC0000017L; /* Out of Memory */
} else {
NTStatus = 0xC0982001L; /* SMB non-specific error */
}
osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
__FILE__, __LINE__);
+ /* on the first pass hold 'vcp' which was not held as 'nextp' */
+ if (vcp != nextp)
+ smb_HoldVCNoLock(vcp);
+
+ /*
+ * obtain a reference to 'nextp' now because we drop the
+ * smb_rctLock later and the list contents could change
+ * or 'vcp' could be destroyed when released.
+ */
nextp = vcp->nextp;
+ if (nextp)
+ smb_HoldVCNoLock(nextp);
- if (vcp->flags & SMB_VCFLAG_ALREADYDEAD)
+ if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
+ smb_ReleaseVCNoLock(vcp);
continue;
+ }
- smb_HoldVCNoLock(vcp);
- if (nextp)
- smb_HoldVCNoLock(nextp);
smb_FormatResponsePacket(vcp, NULL, outp);
smbp = (smb_t *)outp;
outp->inCom = smbp->com = 0x2b /* Echo */;
lock_ObtainWrite(&smb_rctLock);
smb_ReleaseVCNoLock(vcp);
- if (nextp)
- smb_ReleaseVCNoLock(nextp);
}
lock_ReleaseWrite(&smb_rctLock);
smb_FreePacket(outp);
char *tbp;
tbp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(inp, tbp, &tbp, SMB_STRF_ANSIPATH);
+ if (!pathp)
+ return CM_ERROR_BADSMB;
}
tp = cm_ClientStrRChr(pathp, '\\');
if (!tp)
tidp = smb_FindTID(vcp, newTid, SMB_FLAG_CREATE);
uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
+ if (!uidp)
+ return CM_ERROR_BADSMB;
userp = smb_GetUserFromUID(uidp);
shareFound = smb_FindShare(vcp, uidp, shareName, &sharePath);
- if (uidp)
- smb_ReleaseUID(uidp);
+ smb_ReleaseUID(uidp);
if (!shareFound) {
smb_ReleaseTID(tidp, FALSE);
return CM_ERROR_BADSHARENAME;
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(inp, tp, &tp,
SMB_STRF_ANSIPATH|SMB_STRF_FORCEASCII);
- osi_assertx(pathp != NULL, "null path");
+ if (!pathp)
+ return CM_ERROR_BADSMB;
statBlockp = smb_ParseVblBlock(tp, &tp, &statLen);
osi_assertx(statBlockp != NULL, "null statBlock");
if (statLen == 0) {
switch (scp->fileType) {
case CM_SCACHETYPE_DIRECTORY:
case CM_SCACHETYPE_MOUNTPOINT:
- case CM_SCACHETYPE_SYMLINK:
case CM_SCACHETYPE_INVALID:
attr = SMB_ATTR_DIRECTORY;
break;
+ case CM_SCACHETYPE_SYMLINK:
+ if (cm_TargetPerceivedAsDirectory(scp->mountPointStringp))
+ attr = SMB_ATTR_DIRECTORY;
+ else
+ attr = SMB_ATTR_NORMAL;
+ break;
default:
/* if we get here we either have a normal file
* or we have a file for which we have never
* received status info. In this case, we can
* check the even/odd value of the entry's vnode.
- * even means it is to be treated as a directory
- * and odd means it is to be treated as a file.
+ * odd means it is to be treated as a directory
+ * and even means it is to be treated as a file.
*/
if (mustFake && (scp->fid.vnode & 0x1))
attr = SMB_ATTR_DIRECTORY;
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(inp, tp, &tp,
SMB_STRF_ANSIPATH|SMB_STRF_FORCEASCII);
- inCookiep = smb_ParseVblBlock(tp, &tp, &dataLength);
+ if (!pathp)
+ return CM_ERROR_BADSMB;
- /* bail out if request looks bad */
- if (!tp || !pathp) {
+ inCookiep = smb_ParseVblBlock(tp, &tp, &dataLength);
+ if (!tp)
return CM_ERROR_BADSMB;
- }
/* We can handle long names */
if (vcp->flags & SMB_VCFLAG_USENT)
memcpy(dsp->mask, mask, 12);
/* track if this is likely to match a lot of entries */
- if (smb_IsStarMask(mask))
+ if (smb_Is8Dot3StarMask(mask))
starPattern = 1;
else
starPattern = 0;
code = 0;
returnedNames = 0;
while (1) {
- clientchar_t *actualName;
+ clientchar_t *actualName = NULL;
+ int free_actualName = 0;
clientchar_t shortName[13];
clientchar_t *shortNameEnd;
/* Compute 8.3 name if necessary */
actualName = cm_FsStringToClientStringAlloc(dep->name, -1, NULL);
if (dep->fid.vnode != 0 && !cm_Is8Dot3(actualName)) {
- free(actualName);
+ if (actualName)
+ free(actualName);
cm_Gen8Dot3NameInt(dep->name, &dep->fid, shortName, &shortNameEnd);
actualName = shortName;
+ free_actualName = 0;
+ } else {
+ free_actualName = 1;
+ }
+
+ if (actualName == NULL) {
+ /* Couldn't convert the name for some reason */
+ osi_Log1(smb_logp, "SMB search dir skipping entry :[%s]",
+ osi_LogSaveString(smb_logp, dep->name));
+ goto nextEntry;
}
osi_Log3(smb_logp, "SMB search dir vn %d name %s (%S)",
} /* if we're including this name */
nextEntry:
+ if (free_actualName && actualName) {
+ free(actualName);
+ actualName = NULL;
+ }
+
/* and adjust curOffset to be where the new cookie is */
thyper.HighPart = 0;
thyper.LowPart = CM_DIR_CHUNKSIZE * numDirChunks;
pdata = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(inp, pdata, NULL, SMB_STRF_ANSIPATH);
if (!pathp)
- return CM_ERROR_BADFD;
+ return CM_ERROR_BADSMB;
osi_Log1(smb_logp, "SMB receive check path %S",
osi_LogSaveClientString(smb_logp, pathp));
cm_SyncOpDone(newScp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
-#ifdef undef
- /* use smb_Attributes instead. Also the fact that a file is
- * in a readonly volume doesn't mean it shojuld be marked as RO
- */
- if (newScp->fileType == CM_SCACHETYPE_DIRECTORY ||
- newScp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
- newScp->fileType == CM_SCACHETYPE_INVALID)
- attrs = SMB_ATTR_DIRECTORY;
- else
- attrs = 0;
- if ((newScp->unixModeBits & 0222) == 0 || (newScp->flags & CM_SCACHEFLAG_RO))
- attrs |= SMB_ATTR_READONLY; /* turn on read-only flag */
-#else
attrs = smb_Attributes(newScp);
-#endif
smb_SetSMBParm(outp, 0, attrs);
datap = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(inp, datap, NULL, SMB_STRF_ANSIPATH);
+ if (!pathp)
+ return CM_ERROR_BADSMB;
osi_Log1(smb_logp, "SMB receive open file [%S]", osi_LogSaveClientString(smb_logp, pathp));
}
#endif
+ if (!cm_IsValidClientString(pathp)) {
+#ifdef DEBUG
+ clientchar_t * hexp;
+
+ hexp = cm_GetRawCharsAlloc(pathp, -1);
+ osi_Log1(smb_logp, "CoreOpen rejecting invalid name. [%S]",
+ osi_LogSaveClientString(smb_logp, hexp));
+ if (hexp)
+ free(hexp);
+#else
+ osi_Log0(smb_logp, "CoreOpen rejecting invalid name");
+#endif
+ return CM_ERROR_BADNTFILENAME;
+ }
+
share = smb_GetSMBParm(inp, 0);
attribute = smb_GetSMBParm(inp, 1);
if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
caseFold |= CM_FLAG_8DOT3;
- cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
+ if (cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName)) == 0) {
+ /* Can't convert name */
+ osi_Log1(smb_logp, "Skipping entry [%s]. Can't normalize FS string.",
+ osi_LogSaveString(smb_logp, dep->name));
+ return 0;
+ }
+
match = cm_MatchMask(matchName, rockp->maskp, caseFold);
if (!match &&
(rockp->flags & SMB_MASKFLAG_TILDE) &&
cm_req_t req;
smb_InitReq(&req);
+ memset(&rock, 0, sizeof(rock));
attribute = smb_GetSMBParm(inp, 0);
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
+ if (!pathp)
+ return CM_ERROR_BADSMB;
osi_Log1(smb_logp, "SMB receive unlink %S",
osi_LogSaveClientString(smb_logp, pathp));
rock.any = 0;
rock.maskp = cm_ClientStringToNormStringAlloc(smb_FindMask(pathp), -1, NULL);
+ if (!rock.maskp) {
+ code = CM_ERROR_NOSUCHFILE;
+ goto done;
+ }
rock.flags = ((cm_ClientStrChr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
thyper.LowPart = 0;
osi_Log1(smb_logp, "Unlinking %s",
osi_LogSaveString(smb_logp, entry->name));
+ /* We assume this works because entry->name was
+ successfully converted in smb_UnlinkProc() once. */
cm_FsStringToNormString(entry->name, -1,
normalizedName, lengthof(normalizedName));
cm_DirEntryListFree(&rock.matches);
+ done:
+ if (userp)
cm_ReleaseUser(userp);
+ if (dscp)
cm_ReleaseSCache(dscp);
+ if (rock.maskp)
free(rock.maskp);
if (code == 0 && !rock.any)
rockp = (smb_renameRock_t *) vrockp;
- cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
+ if (cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName)) == 0) {
+ /* Can't convert string */
+ osi_Log1(smb_logp, "Skpping entry [%s]. Can't normalize FS string",
+ osi_LogSaveString(smb_logp, dep->name));
+ return 0;
+ }
+
caseFold = ((rockp->flags & SMB_MASKFLAG_CASEFOLD)? CM_FLAG_CASEFOLD : 0);
if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
caseFold |= CM_FLAG_8DOT3;
}
smb_InitReq(&req);
+ memset(&rock, 0, sizeof(rock));
+
spacep = inp->spacep;
smb_StripLastComponent(spacep->wdata, &oldLastNamep, oldPathp);
/* TODO: The old name could be a wildcard. The new name must not be */
- /* do the vnode call */
- rock.odscp = oldDscp;
- rock.ndscp = newDscp;
- rock.userp = userp;
- rock.reqp = &req;
- rock.vcp = vcp;
- rock.maskp = cm_ClientStringToNormStringAlloc(oldLastNamep, -1, NULL);
- rock.flags = ((cm_ClientStrChr(oldLastNamep, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
- rock.newNamep = newLastNamep;
- rock.fsOldName[0] = '\0';
- rock.clOldName[0] = '\0';
- rock.any = 0;
-
/* 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_BPLUS_NOMATCH) &&
osi_Log0(smb_logp, "Can't rename. Target already exists");
code = CM_ERROR_EXISTS;
}
+ goto done;
+ }
- if (tmpscp != NULL)
- cm_ReleaseSCache(tmpscp);
- cm_ReleaseSCache(newDscp);
- cm_ReleaseSCache(oldDscp);
- cm_ReleaseUser(userp);
-
- free(rock.maskp);
- rock.maskp = NULL;
- return code;
+ /* do the vnode call */
+ rock.odscp = oldDscp;
+ rock.ndscp = newDscp;
+ rock.userp = userp;
+ rock.reqp = &req;
+ rock.vcp = vcp;
+ rock.maskp = cm_ClientStringToNormStringAlloc(oldLastNamep, -1, NULL);
+ if (!rock.maskp) {
+ code = CM_ERROR_NOSUCHFILE;
+ goto done;
}
+ rock.flags = ((cm_ClientStrChr(oldLastNamep, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
+ rock.newNamep = newLastNamep;
+ rock.fsOldName[0] = '\0';
+ rock.clOldName[0] = '\0';
+ rock.any = 0;
/* Now search the directory for the pattern, and do the appropriate rename when found */
thyper.LowPart = 0; /* search dir from here */
}
}
+ done:
if (tmpscp != NULL)
cm_ReleaseSCache(tmpscp);
- cm_ReleaseUser(userp);
- cm_ReleaseSCache(oldDscp);
- cm_ReleaseSCache(newDscp);
-
- free(rock.maskp);
- rock.maskp = NULL;
+ if (userp)
+ cm_ReleaseUser(userp);
+ if (oldDscp)
+ cm_ReleaseSCache(oldDscp);
+ if (newDscp)
+ cm_ReleaseSCache(newDscp);
+ if (rock.maskp)
+ free(rock.maskp);
return code;
}
tp = smb_GetSMBData(inp, NULL);
oldPathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
+ if (!oldPathp)
+ return CM_ERROR_BADSMB;
newPathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
+ if (!newPathp)
+ return CM_ERROR_BADSMB;
osi_Log2(smb_logp, "smb rename [%S] to [%S]",
osi_LogSaveClientString(smb_logp, oldPathp),
osi_LogSaveClientString(smb_logp, newPathp));
+ if (!cm_IsValidClientString(newPathp)) {
+#ifdef DEBUG
+ clientchar_t * hexp;
+
+ hexp = cm_GetRawCharsAlloc(newPathp, -1);
+ osi_Log1(smb_logp, "CoreRename rejecting invalid name. [%S]",
+ osi_LogSaveClientString(smb_logp, hexp));
+ if (hexp)
+ free(hexp);
+#else
+ osi_Log0(smb_logp, "CoreRename rejecting invalid name");
+#endif
+ return CM_ERROR_BADNTFILENAME;
+ }
+
code = smb_Rename(vcp,inp,oldPathp,newPathp,0);
osi_Log1(smb_logp, "smb rename returns 0x%x", code);
rockp = (smb_rmdirRock_t *) vrockp;
- cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
+ if (cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName)) == 0) {
+ osi_Log1(smb_logp, "Skipping entry [%s]. Can't normalize FS string",
+ osi_LogSaveString(smb_logp, dep->name));
+ return 0;
+ }
+
if (rockp->flags & SMB_MASKFLAG_CASEFOLD)
match = (cm_ClientStrCmpI(matchName, rockp->maskp) == 0);
else
cm_req_t req;
smb_InitReq(&req);
+ memset(&rock, 0, sizeof(rock));
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
+ if (!pathp)
+ return CM_ERROR_BADSMB;
spacep = inp->spacep;
smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
rock.any = 0;
rock.maskp = cm_ClientStringToNormStringAlloc(lastNamep, -1, NULL);
+ if (!rock.maskp) {
+ code = CM_ERROR_NOSUCHFILE;
+ goto done;
+ }
rock.flags = ((cm_ClientStrChr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
thyper.LowPart = 0;
for (entry = rock.matches; code == 0 && entry; entry = entry->nextp) {
clientchar_t clientName[MAX_PATH];
+ /* We assume this will succeed because smb_RmdirProc()
+ successfully converted entry->name once above. */
cm_FsStringToClientString(entry->name, -1, clientName, lengthof(clientName));
osi_Log1(smb_logp, "Removing directory %s",
}
}
+ done:
+ if (rock.matches)
cm_DirEntryListFree(&rock.matches);
+ if (userp)
cm_ReleaseUser(userp);
+ if (dscp)
cm_ReleaseSCache(dscp);
if (code == 0 && !rock.any)
code = CM_ERROR_NOSUCHFILE;
+ if (rock.maskp)
free(rock.maskp);
- rock.maskp = NULL;
return code;
}
vrockp = (struct smb_FullNameRock *)rockp;
- cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName));
+ if (cm_FsStringToNormString(dep->name, -1, matchName, lengthof(matchName)) == 0) {
+ osi_Log1(smb_logp, "Skipping entry [%s]. Can't normalize FS string",
+ osi_LogSaveString(smb_logp, dep->name));
+ return 0;
+ }
if (!cm_Is8Dot3(matchName)) {
clientchar_t shortName[13];
lock_ObtainMutex(&fidp->mx);
if (code == 0 && filter != 0 && (fidp->flags & SMB_FID_NTOPEN)
- && (fidp->NTopen_dscp->flags & CM_SCACHEFLAG_ANYWATCH)) {
+ && (fidp->NTopen_dscp->flags & CM_SCACHEFLAG_ANYWATCH))
+ {
+ lock_ReleaseMutex(&fidp->mx);
smb_NotifyChange(FILE_ACTION_MODIFIED, filter,
fidp->NTopen_dscp, fidp->NTopen_pathp,
NULL, TRUE);
- }
- lock_ReleaseMutex(&fidp->mx);
+ } else {
+ lock_ReleaseMutex(&fidp->mx);
+ }
if (code == 0) {
if (smb_AsyncStore > 0) {
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
-
- if (cm_ClientStrCmp(pathp, _C("\\")) == 0)
- return CM_ERROR_EXISTS;
+ if (!pathp)
+ return CM_ERROR_BADSMB;
spacep = inp->spacep;
smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
+ if (cm_ClientStrCmp(pathp, _C("\\")) == 0)
+ return CM_ERROR_EXISTS;
+
userp = smb_GetUserFromVCP(vcp, inp);
caseFold = CM_FLAG_CASEFOLD;
tp = smb_GetSMBData(inp, NULL);
pathp = smb_ParseASCIIBlock(inp, tp, &tp, SMB_STRF_ANSIPATH);
+ if (!pathp)
+ return CM_ERROR_BADSMB;
+
+ if (!cm_IsValidClientString(pathp)) {
+#ifdef DEBUG
+ clientchar_t * hexp;
+
+ hexp = cm_GetRawCharsAlloc(pathp, -1);
+ osi_Log1(smb_logp, "CoreCreate rejecting invalid name. [%S]",
+ osi_LogSaveClientString(smb_logp, hexp));
+ if (hexp)
+ free(hexp);
+#else
+ osi_Log0(smb_logp, "CoreCreate rejecting invalid name");
+#endif
+ return CM_ERROR_BADNTFILENAME;
+ }
spacep = inp->spacep;
smb_StripLastComponent(spacep->wdata, &lastNamep, pathp);
newTime = GetTickCount();
osi_Log2(smb_logp, "Dispatch %s duration %d ms", opName, newTime - oldTime);
+ /* ReceiveV3Tran2A handles its own logging */
+ if (inp->inCom != 0x32 && newTime - oldTime > 45000) {
+ smb_user_t *uidp;
+ smb_fid_t *fidp;
+ clientchar_t *treepath = NULL; /* do not free */
+ clientchar_t *pathname = NULL;
+ cm_fid_t afid = {0,0,0,0,0};
+
+ uidp = smb_FindUID(vcp, smbp->uid, 0);
+ smb_LookupTIDPath(vcp,((smb_t *)inp)->tid, &treepath);
+ fidp = smb_FindFID(vcp, inp->fid, 0);
+
+ if (fidp && fidp->NTopen_pathp)
+ pathname = fidp->NTopen_pathp;
+ else if (inp->stringsp->wdata)
+ pathname = inp->stringsp->wdata;
+
+ if (fidp && fidp->scp)
+ afid = fidp->scp->fid;
+
+ afsi_log("Request %s duration %d ms user %S tid \"%S\" path? \"%S\" afid (%d.%d.%d.%d)",
+ opName, newTime - oldTime,
+ uidp ? uidp->unp->name : NULL,
+ treepath,
+ pathname,
+ afid.cell, afid.volume, afid.vnode, afid.unique);
+
+ if (uidp)
+ smb_ReleaseUID(uidp);
+ if (fidp)
+ smb_ReleaseFID(fidp);
+ }
+
if (oldGen != sessionGen) {
LogEvent(EVENTLOG_WARNING_TYPE, MSG_BAD_SMB_WRONG_SESSION,
newTime - oldTime, ncbp->ncb_length);
if (smbp->com == 0x1d) {
/* Special handling for Write Raw */
raw_write_cont_t rwc;
- EVENT_HANDLE rwevent;
- char eventName[MAX_PATH];
smb_DispatchPacket(vcp, bufp, outbufp, ncbp, &rwc);
if (rwc.code == 0) {
- rwevent = thrd_CreateEvent(NULL, FALSE, FALSE, TEXT("smb_Server() rwevent"));
+ EVENT_HANDLE rwevent;
+ char eventName[MAX_PATH];
+
+ snprintf(eventName, "smb_Server() rwevent %d", myIdx);
+ rwevent = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
if ( GetLastError() == ERROR_ALREADY_EXISTS )
osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
+
ncbp->ncb_command = NCBRECV | ASYNCH;
ncbp->ncb_lsn = (unsigned char) vcp->lsn;
ncbp->ncb_lana_num = vcp->lana;
int cnamelen = MAX_COMPUTERNAME_LENGTH+1;
INT_PTR lana = (INT_PTR) parmp;
char eventName[MAX_PATH];
+ int bridgeCount = 0;
+ int nowildCount = 0;
sprintf(eventName,"smb_Listener_lana_%d", (unsigned char)lana);
ListenerShutdown[lana] = thrd_CreateEvent(NULL, FALSE, FALSE, eventName);
if (code == NRC_NAMERR) {
/* An smb shutdown or Vista resume must have taken place */
- osi_Log2(smb_logp,
+ osi_Log1(smb_logp,
"NCBLISTEN lana=%d failed with NRC_NAMERR.",
- ncbp->ncb_lana_num, code);
+ ncbp->ncb_lana_num);
+ afsi_log("NCBLISTEN lana=%d failed with NRC_NAMERR.", ncbp->ncb_lana_num);
if (lock_TryMutex(&smb_StartedLock)) {
lana_list.lana[i] = LANA_INVALID;
} else if (code == NRC_BRIDGE || code != 0) {
int lanaRemaining = 0;
+ if (code == NRC_BRIDGE) {
+ if (++bridgeCount <= 5) {
+ afsi_log("NCBLISTEN lana=%d failed with NRC_BRIDGE, retrying ...", ncbp->ncb_lana_num);
+ continue;
+ }
+ } else if (code == NRC_NOWILD) {
+ if (++nowildCount <= 5) {
+ afsi_log("NCBLISTEN lana=%d failed with NRC_NOWILD, retrying ...", ncbp->ncb_lana_num);
+
+ if (bridgeCount > 0) {
+ memset(ncbp, 0, sizeof(*ncbp));
+ ncbp->ncb_command = NCBADDNAME;
+ ncbp->ncb_lana_num = (UCHAR)lana;
+ /* pad out with spaces instead of null termination */
+ len = (long)strlen(smb_localNamep);
+ strncpy(ncbp->ncb_name, smb_localNamep, NCBNAMSZ);
+ for (i=len; i<NCBNAMSZ; i++) ncbp->ncb_name[i] = ' ';
+ code = Netbios(ncbp);
+ }
+ continue;
+ }
+ }
+
while (!lock_TryMutex(&smb_StartedLock)) {
if (smb_ListenerState == SMB_LISTENER_STOPPED || smbShutdownFlag == 1)
goto exit_thread;
osi_Log2(smb_logp,
"NCBLISTEN lana=%d failed with %s. Listener thread exiting.",
ncbp->ncb_lana_num, ncb_error_string(code));
+ afsi_log("NCBLISTEN lana=%d failed with %s. Listener thread exiting.",
+ ncbp->ncb_lana_num, ncb_error_string(code));
for (i = 0; i < lana_list.length; i++) {
if (lana_list.lana[i] == lana) {
}
#endif /* 0 */
+ /* a successful packet received. clear bridge error count */
+ bridgeCount = 0;
+ nowildCount = 0;
+
/* check for remote conns */
/* first get remote name and insert null terminator */
memcpy(rname, ncbp->ncb_callname, NCBNAMSZ);
SUCCEEDED(lana_GetUncServerNameEx(NetbiosName, &lanaNum, &bGateway,
LANA_NETBIOS_NAME_FULL)) &&
lanaNum != LANA_INVALID && smb_LANadapter != lanaNum) {
- if ( isGateway != bGateway ||
- strcmp(cm_NetbiosName, NetbiosName) ) {
+ if ( isGateway != bGateway ) {
+ afsi_log("Lan Adapter Change detected (%d != %d): gateway %d != %d",
+ smb_LANadapter, lanaNum, isGateway, bGateway);
+ change = 1;
+ } else if (strcmp(cm_NetbiosName, NetbiosName) ) {
+ afsi_log("Lan Adapter Change detected (%d != %d): name %s != %s",
+ smb_LANadapter, lanaNum, cm_NetbiosName, NetbiosName);
change = 1;
} else {
NCB *ncbp = smb_GetNCB();
ncbp->ncb_length = sizeof(temp_list);
code = Netbios(ncbp);
if (code == 0) {
- if (temp_list.length != lana_list.length)
+ if (temp_list.length != lana_list.length) {
+ afsi_log("Lan Adapter Change detected (%d != %d): lan list length changed %d != %d",
+ smb_LANadapter, lanaNum, temp_list.length, lana_list.length);
change = 1;
- else {
+ } else {
for (i=0; i<lana_list.length; i++) {
if ( temp_list.lana[i] != lana_list.lana[i] ) {
+ afsi_log("Lan Adapter Change detected (%d != %d): lana[%d] %d != %d",
+ smb_LANadapter, lanaNum, i, temp_list.lana[i], lana_list.lana[i]);
change = 1;
break;
}
}
if (change) {
- afsi_log("Lan Adapter Change detected");
smb_StopListeners(1);
smb_RestartListeners(1);
}
memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ);
code = Netbios(ncbp);
- afsi_log("Netbios NCBDELNAME lana=%d code=%d retcode=%d complete=%d",
+ afsi_log("StopListener: Netbios NCBDELNAME lana=%d code=%d retcode=%d complete=%d",
lana, code, ncbp->ncb_retcode, ncbp->ncb_cmd_cplt);
/* and then reset the LANA; this will cause the listener threads to exit */
if (code == 0)
code = ncbp->ncb_retcode;
if (code != 0) {
- afsi_log("Netbios NCBRESET lana %d error code %d", lana, code);
+ afsi_log("StopListener: Netbios NCBRESET lana %d error code %d", lana, code);
} else {
- afsi_log("Netbios NCBRESET lana %d succeeded", lana);
+ afsi_log("StopListener: Netbios NCBRESET lana %d succeeded", lana);
}
if (wait)
if (code == 0)
code = ncbp->ncb_retcode;
if (code != 0) {
- fprintf(stderr, "Netbios NCBDELNAME lana %d error code %d",
+ fprintf(stderr, "Shutdown: Netbios NCBDELNAME lana %d error code %d",
ncbp->ncb_lana_num, code);
}
fflush(stderr);
if (fidp->scp != NULL) {
cm_scache_t * scp;
+ lock_ReleaseWrite(&smb_rctLock);
lock_ObtainMutex(&fidp->mx);
if (fidp->scp != NULL) {
scp = fidp->scp;
cm_ReleaseSCache(scp);
}
lock_ReleaseMutex(&fidp->mx);
+ lock_ObtainWrite(&smb_rctLock);
}
}