diff --git a/src/WINNT/afsd/cm.h b/src/WINNT/afsd/cm.h index 8f3d53ab31..b0cef02e88 100644 --- a/src/WINNT/afsd/cm.h +++ b/src/WINNT/afsd/cm.h @@ -248,4 +248,5 @@ int RXAFS_Lookup (struct rx_connection *, #define CM_ERROR_AMBIGUOUS_FILENAME (CM_ERROR_BASE+41) #define CM_ERROR_BADLOGONTYPE (CM_ERROR_BASE+42) #define CM_ERROR_GSSCONTINUE (CM_ERROR_BASE+43) +#define CM_ERROR_TIDIPC (CM_ERROR_BASE+44) #endif /* __CM_H_ENV__ */ diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 4c86898d71..0809864c16 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -1025,17 +1025,23 @@ cm_user_t *smb_GetUser(smb_vc_t *vcp, smb_packet_t *inp) * Return a pointer to a pathname extracted from a TID structure. The * TID structure is not held; assume it won't go away. */ -char *smb_GetTIDPath(smb_vc_t *vcp, unsigned short tid) +long smb_LookupTIDPath(smb_vc_t *vcp, unsigned short tid, char ** treepath) { smb_tid_t *tidp; - char *tpath; + long code = 0; tidp = smb_FindTID(vcp, tid, 0); - if (!tidp) - return NULL; - tpath = tidp->pathname; + if (!tidp) { + *treepath = NULL; + } else { + if(tidp->flags & SMB_TIDFLAG_IPC) { + code = CM_ERROR_TIDIPC; + /* tidp->pathname would be NULL, but that's fine */ + } + *treepath = tidp->pathname; smb_ReleaseTID(tidp); - return tpath; + } + return code; } /* check to see if we have a chained fid, that is, a fid that comes from an @@ -1263,6 +1269,37 @@ int smb_ListShares() return num_shares; } #endif /* DJGPP */ + +typedef struct smb_findShare_rock { + char * shareName; + char * match; + int matchType; +} smb_findShare_rock_t; + +#define SMB_FINDSHARE_EXACT_MATCH 1 +#define SMB_FINDSHARE_PARTIAL_MATCH 2 + +long smb_FindShareProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp, + osi_hyper_t *offp) +{ + int matchType = 0; + smb_findShare_rock_t * vrock = (smb_findShare_rock_t *) rockp; + if(!strnicmp(dep->name, vrock->shareName, 12)) { + if(!stricmp(dep->name, vrock->shareName)) + matchType = SMB_FINDSHARE_EXACT_MATCH; + else + matchType = SMB_FINDSHARE_PARTIAL_MATCH; + if(vrock->match) free(vrock->match); + vrock->match = strdup(dep->name); + vrock->matchType = matchType; + + if(matchType == SMB_FINDSHARE_EXACT_MATCH) + return CM_ERROR_STOPNOW; + } + return 0; +} + + /* find a shareName in the table of submounts */ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName, char **pathNamep) @@ -1386,11 +1423,40 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName, *pathNamep = strdup(p); return 1; } - else /* create \\\ */ + else { + /* First lookup shareName in root.afs */ + cm_req_t req; + smb_findShare_rock_t vrock; + osi_hyper_t thyper; char * p = shareName; int rw = 0; + /* attempt to locate a partial match in root.afs. This is because + when using the ANSI RAP calls, the share name is limited to 13 chars + and hence is truncated. Of course we prefer exact matches. */ + cm_InitReq(&req); + thyper.HighPart = 0; + thyper.LowPart = 0; + + vrock.shareName = shareName; + vrock.match = NULL; + vrock.matchType = 0; + + cm_HoldSCache(cm_rootSCachep); + code = cm_ApplyDir(cm_rootSCachep, smb_FindShareProc, &vrock, &thyper, + (uidp? (uidp->unp ? uidp->unp->userp : NULL) : NULL), &req, NULL); + cm_ReleaseSCache(cm_rootSCachep); + + if(vrock.matchType) { + sprintf(pathName,"/%s/",vrock.match); + *pathNamep = strdup(strlwr(pathName)); + free(vrock.match); + return 1; + } + + /* if we get here, there was no match for the share in root.afs */ + /* so try to create \\\ */ if ( *p == '.' ) { p++; rw = 1; @@ -3298,7 +3364,14 @@ long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou spacep = inp->spacep; smb_StripLastComponent(spacep->data, NULL, pathp); lock_ReleaseMutex(&dsp->mx); - tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid); + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); + if(code) { + lock_ReleaseMutex(&dsp->mx); + cm_ReleaseUser(userp); + smb_DeleteDirSearch(dsp); + smb_ReleaseDirSearch(dsp); + return CM_ERROR_NOFILES; + } code = cm_NameI(cm_rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW, userp, tidPathp, &req, &scp); lock_ObtainMutex(&dsp->mx); @@ -3675,7 +3748,11 @@ long smb_ReceiveCoreCheckPath(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou caseFold = CM_FLAG_CASEFOLD; - tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid); + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); + if(code) { + cm_ReleaseUser(userp); + return CM_ERROR_NOSUCHPATH; + } code = cm_NameI(rootScp, pathp, caseFold | CM_FLAG_FOLLOW | CM_FLAG_CHECKPATH, userp, tidPathp, &req, &newScp); @@ -3744,7 +3821,11 @@ long smb_ReceiveCoreSetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack caseFold = CM_FLAG_CASEFOLD; - tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid); + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); + if(code) { + cm_ReleaseUser(userp); + return CM_ERROR_NOSUCHFILE; + } code = cm_NameI(rootScp, pathp, caseFold | CM_FLAG_FOLLOW, userp, tidPathp, &req, &newScp); @@ -3842,7 +3923,11 @@ long smb_ReceiveCoreGetFileAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_pack /* we shouldn't need this for V3 requests, but we seem to */ caseFold = CM_FLAG_CASEFOLD; - tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid); + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); + if(code) { + cm_ReleaseUser(userp); + return CM_ERROR_NOSUCHFILE; + } /* * XXX Strange hack XXX @@ -4020,7 +4105,11 @@ long smb_ReceiveCoreOpen(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) caseFold = CM_FLAG_CASEFOLD; - tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid); + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); + if(code) { + cm_ReleaseUser(userp); + return CM_ERROR_NOSUCHPATH; + } code = cm_NameI(cm_rootSCachep, pathp, caseFold | CM_FLAG_FOLLOW, userp, tidPathp, &req, &scp); @@ -4170,7 +4259,11 @@ long smb_ReceiveCoreUnlink(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD; - tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid); + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); + if(code) { + cm_ReleaseUser(userp); + return CM_ERROR_NOSUCHPATH; + } code = cm_NameI(cm_rootSCachep, spacep->data, caseFold, userp, tidPathp, &req, &dscp); @@ -4320,7 +4413,11 @@ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) */ caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD; - tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid); + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); + if(code) { + cm_ReleaseUser(userp); + return CM_ERROR_NOSUCHPATH; + } code = cm_NameI(cm_rootSCachep, spacep->data, caseFold, userp, tidPathp, &req, &oldDscp); @@ -4519,7 +4616,11 @@ long smb_ReceiveCoreRemoveDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *ou caseFold = CM_FLAG_CASEFOLD; - tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid); + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); + if(code) { + cm_ReleaseUser(userp); + return CM_ERROR_NOSUCHPATH; + } code = cm_NameI(cm_rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW, userp, tidPathp, &req, &dscp); @@ -5522,7 +5623,11 @@ long smb_ReceiveCoreMakeDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp caseFold = CM_FLAG_CASEFOLD; - tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid); + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); + if(code) { + cm_ReleaseUser(userp); + return CM_ERROR_NOSUCHPATH; + } code = cm_NameI(cm_rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW | CM_FLAG_CHECKPATH, @@ -5629,7 +5734,11 @@ long smb_ReceiveCoreCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) caseFold = CM_FLAG_CASEFOLD; - tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid); + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); + if(code) { + cm_ReleaseUser(userp); + return CM_ERROR_NOSUCHPATH; + } code = cm_NameI(cm_rootSCachep, spacep->data, caseFold | CM_FLAG_FOLLOW, userp, tidPathp, &req, &dscp); diff --git a/src/WINNT/afsd/smb.h b/src/WINNT/afsd/smb.h index 21440036d7..904b14613a 100644 --- a/src/WINNT/afsd/smb.h +++ b/src/WINNT/afsd/smb.h @@ -412,7 +412,7 @@ extern void smb_ReleaseUID(smb_user_t *uidp); extern cm_user_t *smb_GetUser(smb_vc_t *vcp, smb_packet_t *inp); -extern char *smb_GetTIDPath(smb_vc_t *vcp, unsigned short tid); +extern long smb_LookupTIDPath(smb_vc_t *vcp, unsigned short tid, char ** tidPathp); extern smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags); diff --git a/src/WINNT/afsd/smb3.c b/src/WINNT/afsd/smb3.c index 54b578f0ac..0963f7512c 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -940,6 +940,10 @@ long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *o } strcpy(shareName, tp+1); + osi_Log2(smb_logp, "Tree connect pathp[%s] shareName[%s]", + osi_LogSaveString(smb_logp, pathp), + osi_LogSaveString(smb_logp, shareName)); + if (strcmp(servicep, "IPC") == 0 || strcmp(shareName, "IPC$") == 0) { #ifndef NO_IPC osi_Log0(smb_logp, "TreeConnectX connecting to IPC$"); @@ -1756,9 +1760,92 @@ long smb_ReceiveRAPNetWkstaGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_pack return code; } +typedef struct smb_rap_server_info_0 { + char sv0_name[16]; +} smb_rap_server_info_0_t; + +typedef struct smb_rap_server_info_1 { + char sv1_name[16]; + char sv1_version_major; + char sv1_version_minor; + unsigned long sv1_type; + DWORD *sv1_comment_or_master_browser; /* char *sv1_comment_or_master_browser;*/ +} smb_rap_server_info_1_t; + +char smb_ServerComment[] = "OpenAFS Client"; +int smb_ServerCommentLen = sizeof(smb_ServerComment); + +#define SMB_SV_TYPE_SERVER 0x00000002L +#define SMB_SV_TYPE_NT 0x00001000L +#define SMB_SV_TYPE_SERVER_NT 0x00008000L + long smb_ReceiveRAPNetServerGetInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) { - return CM_ERROR_BADOP; + smb_tran2Packet_t *outp; + long code = 0; + int infoLevel; + int bufsize; + unsigned short * tp; + int totalData; + int totalParams; + smb_rap_server_info_0_t * info0; + smb_rap_server_info_1_t * info1; + char * cstrp; + + tp = p->parmsp + 1; /* Skip over function number */ + (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over param descriptor */ + (void) smb_ParseString((unsigned char*) tp, (char **) &tp); /* skip over data descriptor */ + infoLevel = *tp++; + bufsize = *tp++; + + if(infoLevel != 0 && infoLevel != 1) { + return CM_ERROR_INVAL; + } + + totalParams = 6; + + totalData = + (infoLevel == 0) ? sizeof(smb_rap_server_info_0_t) + : (sizeof(smb_rap_server_info_1_t) + smb_ServerCommentLen); + + outp = smb_GetTran2ResponsePacket(vcp, p, op, totalParams, totalData); + + memset(outp->parmsp,0,totalParams); + memset(outp->datap,0,totalData); + + if(infoLevel == 0) { + info0 = (smb_rap_share_info_0_t *) outp->datap; + cstrp = (char *) (info0 + 1); + strcpy(info0->sv0_name, "AFS"); + } else { /* infoLevel == 1 */ + info1 = (smb_rap_share_info_1_t *) outp->datap; + cstrp = (char *) (info1 + 1); + strcpy(info1->sv1_name, "AFS"); + + info1->sv1_type = + SMB_SV_TYPE_SERVER | + SMB_SV_TYPE_NT | + SMB_SV_TYPE_SERVER_NT; + + info1->sv1_version_major = 5; + info1->sv1_version_minor = 1; + info1->sv1_comment_or_master_browser = (DWORD) (cstrp - outp->datap); + + strcpy(cstrp, smb_ServerComment); + + cstrp += smb_ServerCommentLen; + } + + totalData = cstrp - outp->datap; + outp->totalData = min(bufsize,totalData); /* actual data size */ + outp->parmsp[0] = (outp->totalData == totalData)? 0 : ERROR_MORE_DATA; + outp->parmsp[2] = totalData; + outp->totalParms = totalParams; + + smb_SendTran2Packet(vcp,outp,op); + smb_FreeTran2Packet(outp); + + return code; } long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) @@ -2006,7 +2093,16 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) return CM_ERROR_BADSMB; } - tidPathp = smb_GetTIDPath(vcp, p->tid); + code = smb_LookupTIDPath(vcp, p->tid, &tidPathp); + if(code == CM_ERROR_TIDIPC) { + /* Attempt to use TID allocated for IPC. The client is + probably trying to locate DCE RPC end points, which + we don't support. */ + osi_Log0(smb_logp, "Tran2Open received IPC TID"); + cm_ReleaseUser(userp); + smb_FreeTran2Packet(outp); + return CM_ERROR_NOSUCHPATH; + } dscp = NULL; code = cm_NameI(cm_rootSCachep, pathp, @@ -2429,7 +2525,13 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t return CM_ERROR_BADSMB; } - tidPathp = smb_GetTIDPath(vcp, p->tid); + code = smb_LookupTIDPath(vcp, p->tid, &tidPathp); + if(code) { + cm_ReleaseUser(userp); + smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOSUCHPATH); + smb_FreeTran2Packet(outp); + return 0; + } /* * XXX Strange hack XXX @@ -3368,7 +3470,15 @@ long smb_ReceiveTran2SearchDir(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t smb_StripLastComponent(spacep->data, NULL, pathp); lock_ReleaseMutex(&dsp->mx); - tidPathp = smb_GetTIDPath(vcp, p->tid); + code = smb_LookupTIDPath(vcp, p->tid, &tidPathp); + if(code) { + cm_ReleaseUser(userp); + smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOFILES); + smb_FreeTran2Packet(outp); + smb_DeleteDirSearch(dsp); + smb_ReleaseDirSearch(dsp); + return 0; + } code = cm_NameI(cm_rootSCachep, spacep->data, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp); @@ -3958,7 +4068,11 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) userp = smb_GetUser(vcp, inp); dscp = NULL; - tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid); + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); + if(code) { + cm_ReleaseUser(userp); + return CM_ERROR_NOSUCHPATH; + } code = cm_NameI(cm_rootSCachep, pathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp); @@ -4603,7 +4717,16 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) if (baseFid == 0) { baseDirp = cm_rootSCachep; - tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid); + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); + if(code == CM_ERROR_TIDIPC) { + /* Attempt to use a TID allocated for IPC. The client + is probably looking for DCE RPC end points which we + don't support. */ + osi_Log0(smb_logp, "NTCreateX received IPC TID"); + free(realPathp); + cm_ReleaseUser(userp); + return CM_ERROR_NOSUCHFILE; + } } else { baseFidp = smb_FindFID(vcp, baseFid, 0); @@ -5118,7 +5241,16 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out if (baseFid == 0) { baseDirp = cm_rootSCachep; - tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid); + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); + if(code == CM_ERROR_TIDIPC) { + /* Attempt to use TID allocated for IPC. The client is + probably trying to locate DCE RPC endpoints, which we + don't support. */ + osi_Log0(smb_logp, "NTTranCreate received IPC TID"); + free(realPathp); + cm_ReleaseUser(userp); + return CM_ERROR_NOSUCHPATH; + } } else { baseFidp = smb_FindFID(vcp, baseFid, 0); diff --git a/src/WINNT/afsd/smb_ioctl.c b/src/WINNT/afsd/smb_ioctl.c index 32d2bebc05..c35849dd45 100644 --- a/src/WINNT/afsd/smb_ioctl.c +++ b/src/WINNT/afsd/smb_ioctl.c @@ -181,7 +181,11 @@ long smb_IoctlRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, userp = smb_GetUser(vcp, inp); /* Identify tree */ - iop->tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid); + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp); + if(code) { + cm_ReleaseUser(userp); + return CM_ERROR_NOSUCHPATH; + } /* turn the connection around, if required */ code = smb_IoctlPrepareRead(fidp, iop, userp); @@ -294,7 +298,13 @@ long smb_IoctlV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_pack userp); } - iop->tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid); + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp); + if(code) { + smb_ReleaseUID(uidp); + cm_ReleaseUser(userp); + smb_ReleaseFID(fidp); + return CM_ERROR_NOSUCHPATH; + } code = smb_IoctlPrepareRead(fidp, iop, userp); if (uidp) { @@ -392,7 +402,12 @@ long smb_IoctlReadRaw(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, if (uidp) smb_ReleaseUID(uidp); } - iop->tidPathp = smb_GetTIDPath(vcp, ((smb_t *)inp)->tid); + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &iop->tidPathp); + if(code) { + cm_ReleaseUser(userp); + smb_ReleaseFID(fidp); + return CM_ERROR_NOSUCHPATH; + } code = smb_IoctlPrepareRead(fidp, iop, userp); if (code) {