2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afs/param.h>
17 #include <sys/timeb.h>
29 #include <rx/rx_prototypes.h>
32 #include <WINNT\afsreg.h>
35 #include "lanahelper.h"
37 /* These characters are illegal in Windows filenames */
38 static char *illegalChars = "\\/:*?\"<>|";
39 BOOL isWindows2000 = FALSE;
41 smb_vc_t *dead_vcp = NULL;
42 smb_vc_t *active_vcp = NULL;
44 /* TODO; logout mechanism needs to be thread-safe */
45 char *loggedOutName = NULL;
46 smb_user_t *loggedOutUserp = NULL;
49 int smbShutdownFlag = 0;
51 int smb_LogoffTokenTransfer;
52 time_t smb_LogoffTransferTimeout;
54 int smb_StoreAnsiFilenames = 0;
56 DWORD last_msg_time = 0;
60 unsigned int sessionGen = 0;
62 extern void afsi_log(char *pattern, ...);
63 extern HANDLE afsi_file;
65 osi_hyper_t hzero = {0, 0};
66 osi_hyper_t hones = {0xFFFFFFFF, -1};
69 osi_rwlock_t smb_globalLock;
70 osi_rwlock_t smb_rctLock;
71 osi_mutex_t smb_ListenerLock;
74 unsigned char smb_sharename[NCBNAMSZ+1] = {0};
77 long smb_maxObsConcurrentCalls=0;
78 long smb_concurrentCalls=0;
80 smb_dispatch_t smb_dispatchTable[SMB_NOPCODES];
82 smb_packet_t *smb_packetFreeListp;
83 smb_ncb_t *smb_ncbFreeListp;
85 int smb_NumServerThreads;
87 int numNCBs, numSessions, numVCs;
89 int smb_maxVCPerServer;
90 int smb_maxMpxRequests;
92 int smb_authType = SMB_AUTH_EXTENDED; /* type of SMB auth to use. One of SMB_AUTH_* */
94 ULONG smb_lsaSecPackage;
95 LSA_STRING smb_lsaLogonOrigin;
97 #define NCBmax MAXIMUM_WAIT_OBJECTS
98 EVENT_HANDLE NCBavails[NCBmax], NCBevents[NCBmax];
99 EVENT_HANDLE **NCBreturns;
100 EVENT_HANDLE **NCBShutdown;
101 EVENT_HANDLE *smb_ServerShutdown;
102 DWORD NCBsessions[NCBmax];
104 struct smb_packet *bufs[NCBmax];
106 #define Sessionmax MAXIMUM_WAIT_OBJECTS - 4
107 EVENT_HANDLE SessionEvents[Sessionmax];
108 unsigned short LSNs[Sessionmax];
109 int lanas[Sessionmax];
110 BOOL dead_sessions[Sessionmax];
114 osi_mutex_t smb_RawBufLock;
116 #define SMB_RAW_BUFS 4
118 int smb_RawBufSel[SMB_RAW_BUFS];
123 #define SMB_MASKFLAG_TILDE 1
124 #define SMB_MASKFLAG_CASEFOLD 2
126 #define RAWTIMEOUT INFINITE
129 typedef struct raw_write_cont {
142 /* dir search stuff */
143 long smb_dirSearchCounter = 1;
144 smb_dirSearch_t *smb_firstDirSearchp;
145 smb_dirSearch_t *smb_lastDirSearchp;
147 /* hide dot files? */
148 int smb_hideDotFiles;
150 /* global state about V3 protocols */
151 int smb_useV3; /* try to negotiate V3 */
154 static showErrors = 1;
155 /* MessageBox or something like it */
156 int (_stdcall *smb_MBfunc)(HWND, LPCTSTR, LPCTSTR, UINT) = NULL;
160 * Time in Unix format of midnight, 1/1/1970 local time.
161 * When added to dosUTime, gives Unix (AFS) time.
163 time_t smb_localZero = 0;
165 #define USE_NUMERIC_TIME_CONV 1
167 #ifndef USE_NUMERIC_TIME_CONV
168 /* Time difference for converting to kludge-GMT */
169 afs_uint32 smb_NowTZ;
170 #endif /* USE_NUMERIC_TIME_CONV */
172 char *smb_localNamep = NULL;
174 smb_vc_t *smb_allVCsp;
176 smb_username_t *usernamesp = NULL;
178 smb_waitingLockRequest_t *smb_allWaitingLocks;
181 void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
182 NCB *ncbp, raw_write_cont_t *rwcp);
183 void smb_NetbiosInit();
185 #ifndef AFS_WIN95_ENV
186 DWORD smb_ServerExceptionFilter(void);
189 extern char cm_HostName[];
190 extern char cm_confDir[];
194 #define LPTSTR char *
195 #define GetComputerName(str, sizep) \
196 strcpy((str), cm_HostName); \
197 *(sizep) = strlen(cm_HostName)
201 void smb_LogPacket(smb_packet_t *packet);
202 #endif /* LOG_PACKET */
204 char smb_ServerDomainName[MAX_COMPUTERNAME_LENGTH + 1] = ""; /* domain name */
205 int smb_ServerDomainNameLength = 0;
206 char smb_ServerOS[] = "Windows 5.0"; /* Faux OS String */
207 int smb_ServerOSLength = sizeof(smb_ServerOS);
208 char smb_ServerLanManager[] = "Windows 2000 LAN Manager"; /* Faux LAN Manager string */
209 int smb_ServerLanManagerLength = sizeof(smb_ServerLanManager);
211 /* Faux server GUID. This is never checked. */
212 GUID smb_ServerGUID = { 0x40015cb8, 0x058a, 0x44fc, { 0xae, 0x7e, 0xbb, 0x29, 0x52, 0xee, 0x7e, 0xff }};
214 char * myCrt_Dispatch(int i)
219 return "(00)ReceiveCoreMakeDir";
221 return "(01)ReceiveCoreRemoveDir";
223 return "(02)ReceiveCoreOpen";
225 return "(03)ReceiveCoreCreate";
227 return "(04)ReceiveCoreClose";
229 return "(05)ReceiveCoreFlush";
231 return "(06)ReceiveCoreUnlink";
233 return "(07)ReceiveCoreRename";
235 return "(08)ReceiveCoreGetFileAttributes";
237 return "(09)ReceiveCoreSetFileAttributes";
239 return "(0a)ReceiveCoreRead";
241 return "(0b)ReceiveCoreWrite";
243 return "(0c)ReceiveCoreLockRecord";
245 return "(0d)ReceiveCoreUnlockRecord";
247 return "(0e)SendCoreBadOp";
249 return "(0f)ReceiveCoreCreate";
251 return "(10)ReceiveCoreCheckPath";
253 return "(11)SendCoreBadOp";
255 return "(12)ReceiveCoreSeek";
257 return "(1a)ReceiveCoreReadRaw";
259 return "(1d)ReceiveCoreWriteRawDummy";
261 return "(22)ReceiveV3SetAttributes";
263 return "(23)ReceiveV3GetAttributes";
265 return "(24)ReceiveV3LockingX";
267 return "(25)ReceiveV3Trans";
269 return "(26)ReceiveV3Trans[aux]";
271 return "(29)SendCoreBadOp";
273 return "(2b)ReceiveCoreEcho";
275 return "(2d)ReceiveV3OpenX";
277 return "(2e)ReceiveV3ReadX";
279 return "(32)ReceiveV3Tran2A";
281 return "(33)ReceiveV3Tran2A[aux]";
283 return "(34)ReceiveV3FindClose";
285 return "(35)ReceiveV3FindNotifyClose";
287 return "(70)ReceiveCoreTreeConnect";
289 return "(71)ReceiveCoreTreeDisconnect";
291 return "(72)ReceiveNegotiate";
293 return "(73)ReceiveV3SessionSetupX";
295 return "(74)ReceiveV3UserLogoffX";
297 return "(75)ReceiveV3TreeConnectX";
299 return "(80)ReceiveCoreGetDiskAttributes";
301 return "(81)ReceiveCoreSearchDir";
305 return "(83)FindUnique";
307 return "(84)FindClose";
309 return "(A0)ReceiveNTTransact";
311 return "(A2)ReceiveNTCreateX";
313 return "(A4)ReceiveNTCancel";
315 return "(A5)ReceiveNTRename";
317 return "(C0)OpenPrintFile";
319 return "(C1)WritePrintFile";
321 return "(C2)ClosePrintFile";
323 return "(C3)GetPrintQueue";
325 return "(D8)ReadBulk";
327 return "(D9)WriteBulk";
329 return "(DA)WriteBulkData";
331 return "unknown SMB op";
335 char * myCrt_2Dispatch(int i)
340 return "unknown SMB op-2";
342 return "S(00)CreateFile";
344 return "S(01)FindFirst";
346 return "S(02)FindNext"; /* FindNext */
348 return "S(03)QueryFileSystem_ReceiveTran2QFSInfo";
352 return "S(05)QueryFileInfo_ReceiveTran2QPathInfo";
354 return "S(06)SetFileInfo_ReceiveTran2SetPathInfo";
356 return "S(07)SetInfoHandle_ReceiveTran2QFileInfo";
358 return "S(08)??_ReceiveTran2SetFileInfo";
360 return "S(09)??_ReceiveTran2FSCTL";
362 return "S(0a)_ReceiveTran2IOCTL";
364 return "S(0b)_ReceiveTran2FindNotifyFirst";
366 return "S(0c)_ReceiveTran2FindNotifyNext";
368 return "S(0d)_ReceiveTran2CreateDirectory";
370 return "S(0e)_ReceiveTran2SessionSetup";
372 return "S(10)_ReceiveTran2GetDfsReferral";
374 return "S(11)_ReceiveTran2ReportDfsInconsistency";
378 char * myCrt_RapDispatch(int i)
383 return "unknown RAP OP";
385 return "RAP(0)NetShareEnum";
387 return "RAP(1)NetShareGetInfo";
389 return "RAP(13)NetServerGetInfo";
391 return "RAP(63)NetWkStaGetInfo";
395 /* scache must be locked */
396 unsigned int smb_Attributes(cm_scache_t *scp)
400 if ( scp->fileType == CM_SCACHETYPE_DIRECTORY ||
401 scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
402 scp->fileType == CM_SCACHETYPE_INVALID)
404 attrs = SMB_ATTR_DIRECTORY;
405 #ifdef SPECIAL_FOLDERS
406 attrs |= SMB_ATTR_SYSTEM; /* FILE_ATTRIBUTE_SYSTEM */
407 #endif /* SPECIAL_FOLDERS */
408 } else if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
409 attrs = SMB_ATTR_DIRECTORY | SMB_ATTR_SPARSE_FILE;
414 * We used to mark a file RO if it was in an RO volume, but that
415 * turns out to be impolitic in NT. See defect 10007.
418 if ((scp->unixModeBits & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
419 attrs |= SMB_ATTR_READONLY; /* turn on read-only flag */
421 if ((scp->unixModeBits & 0222) == 0)
422 attrs |= SMB_ATTR_READONLY; /* turn on read-only flag */
428 /* Check if the named file/dir is a dotfile/dotdir */
429 /* String pointed to by lastComp can have leading slashes, but otherwise should have
430 no other patch components */
431 unsigned int smb_IsDotFile(char *lastComp) {
434 /* skip over slashes */
435 for(s=lastComp;*s && (*s == '\\' || *s == '/'); s++);
440 /* nulls, curdir and parent dir doesn't count */
446 if(*(s+1) == '.' && !*(s + 2))
453 static int ExtractBits(WORD bits, short start, short len)
460 num = bits << (16 - end);
461 num = num >> ((16 - end) + start);
467 void ShowUnixTime(char *FuncName, time_t unixTime)
472 smb_LargeSearchTimeFromUnixTime(&ft, unixTime);
474 if (!FileTimeToDosDateTime(&ft, &wDate, &wTime))
475 osi_Log1(smb_logp, "Failed to convert filetime to dos datetime: %d", GetLastError());
477 int day, month, year, sec, min, hour;
480 day = ExtractBits(wDate, 0, 5);
481 month = ExtractBits(wDate, 5, 4);
482 year = ExtractBits(wDate, 9, 7) + 1980;
484 sec = ExtractBits(wTime, 0, 5);
485 min = ExtractBits(wTime, 5, 6);
486 hour = ExtractBits(wTime, 11, 5);
488 sprintf(msg, "%s = %02d-%02d-%04d %02d:%02d:%02d", FuncName, month, day, year, hour, min, sec);
489 osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, msg));
495 /* Determine if we are observing daylight savings time */
496 void GetTimeZoneInfo(BOOL *pDST, LONG *pDstBias, LONG *pBias)
498 TIME_ZONE_INFORMATION timeZoneInformation;
499 SYSTEMTIME utc, local, localDST;
501 /* Get the time zone info. NT uses this to calc if we are in DST. */
502 GetTimeZoneInformation(&timeZoneInformation);
504 /* Return the daylight bias */
505 *pDstBias = timeZoneInformation.DaylightBias;
507 /* Return the bias */
508 *pBias = timeZoneInformation.Bias;
510 /* Now determine if DST is being observed */
512 /* Get the UTC (GMT) time */
515 /* Convert UTC time to local time using the time zone info. If we are
516 observing DST, the calculated local time will include this.
518 SystemTimeToTzSpecificLocalTime(&timeZoneInformation, &utc, &localDST);
520 /* Set the daylight bias to 0. The daylight bias is the amount of change
521 * in time that we use for daylight savings time. By setting this to 0
522 * we cause there to be no change in time during daylight savings time.
524 timeZoneInformation.DaylightBias = 0;
526 /* Convert the utc time to local time again, but this time without any
527 adjustment for daylight savings time.
529 SystemTimeToTzSpecificLocalTime(&timeZoneInformation, &utc, &local);
531 /* If the two times are different, then it means that the localDST that
532 we calculated includes the daylight bias, and therefore we are
533 observing daylight savings time.
535 *pDST = localDST.wHour != local.wHour;
538 /* Determine if we are observing daylight savings time */
539 void GetTimeZoneInfo(BOOL *pDST, LONG *pDstBias, LONG *pBias)
545 *pDstBias = -60; /* where can this be different? */
551 void CompensateForSmbClientLastWriteTimeBugs(afs_uint32 *pLastWriteTime)
553 BOOL dst; /* Will be TRUE if observing DST */
554 LONG dstBias; /* Offset from local time if observing DST */
555 LONG bias; /* Offset from GMT for local time */
558 * This function will adjust the last write time to compensate
559 * for two bugs in the smb client:
561 * 1) During Daylight Savings Time, the LastWriteTime is ahead
562 * in time by the DaylightBias (ignoring the sign - the
563 * DaylightBias is always stored as a negative number). If
564 * the DaylightBias is -60, then the LastWriteTime will be
565 * ahead by 60 minutes.
567 * 2) If the local time zone is a positive offset from GMT, then
568 * the LastWriteTime will be the correct local time plus the
569 * Bias (ignoring the sign - a positive offset from GMT is
570 * always stored as a negative Bias). If the Bias is -120,
571 * then the LastWriteTime will be ahead by 120 minutes.
573 * These bugs can occur at the same time.
576 GetTimeZoneInfo(&dst, &dstBias, &bias);
578 /* First adjust for DST */
580 *pLastWriteTime -= (-dstBias * 60); /* Convert dstBias to seconds */
582 /* Now adjust for a positive offset from GMT (a negative bias). */
584 *pLastWriteTime -= (-bias * 60); /* Convert bias to seconds */
587 #ifndef USE_NUMERIC_TIME_CONV
589 * Calculate the difference (in seconds) between local time and GMT.
590 * This enables us to convert file times to kludge-GMT.
596 struct tm gmt_tm, local_tm;
597 int days, hours, minutes, seconds;
600 gmt_tm = *(gmtime(&t));
601 local_tm = *(localtime(&t));
603 days = local_tm.tm_yday - gmt_tm.tm_yday;
604 hours = 24 * days + local_tm.tm_hour - gmt_tm.tm_hour;
605 minutes = 60 * hours + local_tm.tm_min - gmt_tm.tm_min;
606 seconds = 60 * minutes + local_tm.tm_sec - gmt_tm.tm_sec;
610 #endif /* USE_NUMERIC_TIME_CONV */
613 #ifdef USE_NUMERIC_TIME_CONV
614 void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
616 // Note that LONGLONG is a 64-bit value
619 ll = Int32x32To64(unixTime, 10000000) + 116444736000000000;
620 largeTimep->dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
621 largeTimep->dwHighDateTime = (DWORD)(ll >> 32);
624 void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
629 time_t ersatz_unixTime;
632 * Must use kludge-GMT instead of real GMT.
633 * kludge-GMT is computed by adding time zone difference to localtime.
636 * ltp = gmtime(&unixTime);
638 ersatz_unixTime = unixTime - smb_NowTZ;
639 ltp = localtime(&ersatz_unixTime);
641 /* if we fail, make up something */
644 localJunk.tm_year = 89 - 20;
645 localJunk.tm_mon = 4;
646 localJunk.tm_mday = 12;
647 localJunk.tm_hour = 0;
648 localJunk.tm_min = 0;
649 localJunk.tm_sec = 0;
652 stm.wYear = ltp->tm_year + 1900;
653 stm.wMonth = ltp->tm_mon + 1;
654 stm.wDayOfWeek = ltp->tm_wday;
655 stm.wDay = ltp->tm_mday;
656 stm.wHour = ltp->tm_hour;
657 stm.wMinute = ltp->tm_min;
658 stm.wSecond = ltp->tm_sec;
659 stm.wMilliseconds = 0;
661 SystemTimeToFileTime(&stm, largeTimep);
663 #endif /* USE_NUMERIC_TIME_CONV */
665 void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
667 /* unixTime: seconds since 1/1/1970 00:00:00 GMT */
668 /* FILETIME: 100ns intervals since 1/1/1601 00:00:00 ??? */
669 LARGE_INTEGER *ft = (LARGE_INTEGER *) largeTimep;
671 int leap_years = 89; /* leap years betw 1/1/1601 and 1/1/1970 */
673 /* set ft to number of 100ns intervals betw 1/1/1601 and 1/1/1970 GMT */
674 *ft = ConvertLongToLargeInteger(((EPOCH_YEAR-1601) * 365 + leap_years)
676 *ft = LargeIntegerMultiplyByLong(*ft, 60);
677 *ft = LargeIntegerMultiplyByLong(*ft, 10000000);
680 ut = ConvertLongToLargeInteger(unixTime);
681 ut = LargeIntegerMultiplyByLong(ut, 10000000);
682 *ft = LargeIntegerAdd(*ft, ut);
687 #ifdef USE_NUMERIC_TIME_CONV
688 void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
690 // Note that LONGLONG is a 64-bit value
693 ll = largeTimep->dwHighDateTime;
695 ll += largeTimep->dwLowDateTime;
697 ll -= 116444736000000000;
700 *unixTimep = (DWORD)ll;
702 #else /* USE_NUMERIC_TIME_CONV */
703 void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
709 FileTimeToSystemTime(largeTimep, &stm);
711 lt.tm_year = stm.wYear - 1900;
712 lt.tm_mon = stm.wMonth - 1;
713 lt.tm_wday = stm.wDayOfWeek;
714 lt.tm_mday = stm.wDay;
715 lt.tm_hour = stm.wHour;
716 lt.tm_min = stm.wMinute;
717 lt.tm_sec = stm.wSecond;
720 save_timezone = _timezone;
721 _timezone += smb_NowTZ;
722 *unixTimep = mktime(<);
723 _timezone = save_timezone;
725 #endif /* USE_NUMERIC_TIME_CONV */
727 void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
729 /* unixTime: seconds since 1/1/1970 00:00:00 GMT */
730 /* FILETIME: 100ns intervals since 1/1/1601 00:00:00 GMT? */
731 LARGE_INTEGER *ft = (LARGE_INTEGER *) largeTimep;
735 /* set to number of 100ns intervals betw 1/1/1601 and 1/1/1970 */
736 a = ConvertLongToLargeInteger(((EPOCH_YEAR-1601) * 365 + leap_years) * 24 * 60);
737 a = LargeIntegerMultiplyByLong(a, 60);
738 a = LargeIntegerMultiplyByLong(a, 10000000);
740 /* subtract it from ft */
741 a = LargeIntegerSubtract(*ft, a);
743 /* divide down to seconds */
744 *unixTimep = LargeIntegerDivideByLong(a, 10000000);
748 void smb_SearchTimeFromUnixTime(afs_uint32 *searchTimep, time_t unixTime)
756 ltp = localtime((time_t*) &t);
758 /* if we fail, make up something */
761 localJunk.tm_year = 89 - 20;
762 localJunk.tm_mon = 4;
763 localJunk.tm_mday = 12;
764 localJunk.tm_hour = 0;
765 localJunk.tm_min = 0;
766 localJunk.tm_sec = 0;
769 dosDate = ((ltp->tm_year-80)<<9) | ((ltp->tm_mon+1) << 5) | (ltp->tm_mday);
770 dosTime = (ltp->tm_hour<<11) | (ltp->tm_min << 5) | (ltp->tm_sec / 2);
771 *searchTimep = (dosDate<<16) | dosTime;
774 void smb_UnixTimeFromSearchTime(time_t *unixTimep, afs_uint32 searchTime)
776 unsigned short dosDate;
777 unsigned short dosTime;
780 dosDate = (unsigned short) (searchTime & 0xffff);
781 dosTime = (unsigned short) ((searchTime >> 16) & 0xffff);
783 localTm.tm_year = 80 + ((dosDate>>9) & 0x3f);
784 localTm.tm_mon = ((dosDate >> 5) & 0xf) - 1; /* January is 0 in localTm */
785 localTm.tm_mday = (dosDate) & 0x1f;
786 localTm.tm_hour = (dosTime>>11) & 0x1f;
787 localTm.tm_min = (dosTime >> 5) & 0x3f;
788 localTm.tm_sec = (dosTime & 0x1f) * 2;
789 localTm.tm_isdst = -1; /* compute whether DST in effect */
791 *unixTimep = mktime(&localTm);
794 void smb_DosUTimeFromUnixTime(afs_uint32 *dosUTimep, time_t unixTime)
796 time_t diff_t = unixTime - smb_localZero;
797 #if defined(DEBUG) && !defined(_USE_32BIT_TIME_T)
798 osi_assert(diff_t < _UI32_MAX);
800 *dosUTimep = (afs_uint32)diff_t;
803 void smb_UnixTimeFromDosUTime(time_t *unixTimep, afs_uint32 dosTime)
806 *unixTimep = dosTime + smb_localZero;
808 /* dosTime seems to be already adjusted for GMT */
809 *unixTimep = dosTime;
813 smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
817 lock_ObtainWrite(&smb_rctLock);
818 for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp) {
819 if (lsn == vcp->lsn && lana == vcp->lana) {
820 smb_HoldVCNoLock(vcp);
824 if (!vcp && (flags & SMB_FLAG_CREATE)) {
825 vcp = malloc(sizeof(*vcp));
826 memset(vcp, 0, sizeof(*vcp));
827 vcp->vcID = numVCs++;
831 vcp->uidCounter = 1; /* UID 0 is reserved for blank user */
832 vcp->nextp = smb_allVCsp;
834 lock_InitializeMutex(&vcp->mx, "vc_t mutex");
839 if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
840 /* We must obtain a challenge for extended auth
841 * in case the client negotiates smb v3
843 NTSTATUS nts = STATUS_UNSUCCESSFUL, ntsEx = STATUS_UNSUCCESSFUL;
844 MSV1_0_LM20_CHALLENGE_REQUEST lsaReq;
845 PMSV1_0_LM20_CHALLENGE_RESPONSE lsaResp;
846 ULONG lsaRespSize = 0;
848 lsaReq.MessageType = MsV1_0Lm20ChallengeRequest;
850 nts = LsaCallAuthenticationPackage( smb_lsaHandle,
857 if (nts != STATUS_SUCCESS)
858 osi_Log4(smb_logp,"MsV1_0Lm20ChallengeRequest failure: nts 0x%x ntsEx 0x%x respSize is %u needs %u",
859 nts, ntsEx, sizeof(lsaReq), lsaRespSize);
860 osi_assert(nts == STATUS_SUCCESS); /* this had better work! */
862 memcpy(vcp->encKey, lsaResp->ChallengeToClient, MSV1_0_CHALLENGE_LENGTH);
863 LsaFreeReturnBuffer(lsaResp);
866 memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
868 if (numVCs >= CM_SESSION_RESERVED) {
870 osi_Log0(smb_logp, "WARNING: numVCs wrapping around");
873 lock_ReleaseWrite(&smb_rctLock);
877 int smb_IsStarMask(char *maskp)
882 for(i=0; i<11; i++) {
884 if (tc == '?' || tc == '*' || tc == '>') return 1;
889 void smb_ReleaseVCNoLock(smb_vc_t *vcp)
891 osi_Log2(smb_logp,"smb_ReleaseVCNoLock vcp %x ref %d",vcp, vcp->refCount);
893 osi_assert(vcp->refCount-- != 0);
899 void smb_ReleaseVC(smb_vc_t *vcp)
901 lock_ObtainWrite(&smb_rctLock);
902 osi_Log2(smb_logp,"smb_ReleaseVC vcp %x ref %d",vcp, vcp->refCount);
904 osi_assert(vcp->refCount-- != 0);
908 lock_ReleaseWrite(&smb_rctLock);
911 void smb_HoldVCNoLock(smb_vc_t *vcp)
914 osi_Log2(smb_logp,"smb_HoldVCNoLock vcp %x ref %d",vcp, vcp->refCount);
917 void smb_HoldVC(smb_vc_t *vcp)
919 lock_ObtainWrite(&smb_rctLock);
921 osi_Log2(smb_logp,"smb_HoldVC vcp %x ref %d",vcp, vcp->refCount);
922 lock_ReleaseWrite(&smb_rctLock);
925 void smb_CleanupDeadVC(smb_vc_t *vcp)
935 smb_user_t *userpIter;
936 smb_user_t *userpNext;
940 osi_Log1(smb_logp, "Cleaning up dead vcp 0x%x", vcp);
942 lock_ObtainRead(&smb_rctLock);
943 for (fidpIter = vcp->fidsp; fidpIter; fidpIter = fidpNext) {
944 fidpNext = (smb_fid_t *) osi_QNext(&fidpIter->q);
946 if (fidpIter->flags & SMB_FID_DELETE)
950 osi_Log2(smb_logp, " Cleanup FID %d (fidp=0x%x)", fid, fidpIter);
951 lock_ReleaseRead(&smb_rctLock);
953 fidp = smb_FindFID(vcp, fid, 0);
955 smb_CloseFID(vcp, fidp, NULL, 0);
956 smb_ReleaseFID(fidp);
958 lock_ObtainRead(&smb_rctLock);
961 for (tidpIter = vcp->tidsp; tidpIter; tidpIter = tidpNext) {
962 tidpNext = tidpIter->nextp;
963 if (tidpIter->flags & SMB_TIDFLAG_DELETE)
967 osi_Log2(smb_logp, " Cleanup TID %d (tidp=0x%x)", tid, tidpIter);
968 lock_ReleaseRead(&smb_rctLock);
970 tidp = smb_FindTID(vcp, tid, 0);
973 lock_ObtainMutex(&tidp->mx);
974 tidp->flags |= SMB_TIDFLAG_DELETE;
975 lock_ReleaseMutex(&tidp->mx);
977 smb_ReleaseTID(tidp);
979 lock_ObtainRead(&smb_rctLock);
982 for (userpIter = vcp->usersp; userpIter; userpIter = userpNext) {
983 userpNext = userpIter->nextp;
985 if (userpIter->flags & SMB_USERFLAG_DELETE)
988 uid = userpIter->userID;
989 osi_Log2(smb_logp, " Cleanup UID %d (userp=0x%x)", uid, userpIter);
990 lock_ReleaseRead(&smb_rctLock);
992 userp = smb_FindUID(vcp, uid, 0);
995 lock_ObtainMutex(&userp->mx);
996 userp->flags |= SMB_USERFLAG_DELETE;
997 lock_ReleaseMutex(&userp->mx);
999 smb_ReleaseUID(userp);
1001 lock_ObtainRead(&smb_rctLock);
1004 lock_ReleaseRead(&smb_rctLock);
1006 osi_Log0(smb_logp, "Done cleaning up dead vcp");
1009 smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
1013 lock_ObtainWrite(&smb_rctLock);
1014 for (tidp = vcp->tidsp; tidp; tidp = tidp->nextp) {
1015 if (tid == tidp->tid) {
1020 if (!tidp && (flags & SMB_FLAG_CREATE)) {
1021 tidp = malloc(sizeof(*tidp));
1022 memset(tidp, 0, sizeof(*tidp));
1023 tidp->nextp = vcp->tidsp;
1026 smb_HoldVCNoLock(vcp);
1028 lock_InitializeMutex(&tidp->mx, "tid_t mutex");
1031 lock_ReleaseWrite(&smb_rctLock);
1035 void smb_ReleaseTID(smb_tid_t *tidp)
1042 lock_ObtainWrite(&smb_rctLock);
1043 osi_assert(tidp->refCount-- > 0);
1044 if (tidp->refCount == 0 && (tidp->flags & SMB_TIDFLAG_DELETE)) {
1045 ltpp = &tidp->vcp->tidsp;
1046 for(tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
1050 osi_assert(tp != NULL);
1052 lock_FinalizeMutex(&tidp->mx);
1053 userp = tidp->userp; /* remember to drop ref later */
1055 smb_ReleaseVCNoLock(tidp->vcp);
1058 lock_ReleaseWrite(&smb_rctLock);
1060 cm_ReleaseUser(userp);
1063 smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
1065 smb_user_t *uidp = NULL;
1067 lock_ObtainWrite(&smb_rctLock);
1068 for(uidp = vcp->usersp; uidp; uidp = uidp->nextp) {
1069 if (uid == uidp->userID) {
1071 osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] found-uid[%d] name[%s]",
1073 osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name : ""));
1077 if (!uidp && (flags & SMB_FLAG_CREATE)) {
1078 uidp = malloc(sizeof(*uidp));
1079 memset(uidp, 0, sizeof(*uidp));
1080 uidp->nextp = vcp->usersp;
1083 smb_HoldVCNoLock(vcp);
1085 lock_InitializeMutex(&uidp->mx, "user_t mutex");
1087 osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] new-uid[%d] name[%s]",
1089 osi_LogSaveString(smb_logp,uidp->unp ? uidp->unp->name : ""));
1091 lock_ReleaseWrite(&smb_rctLock);
1095 smb_username_t *smb_FindUserByName(char *usern, char *machine, int flags)
1097 smb_username_t *unp= NULL;
1099 lock_ObtainWrite(&smb_rctLock);
1100 for(unp = usernamesp; unp; unp = unp->nextp) {
1101 if (stricmp(unp->name, usern) == 0 &&
1102 stricmp(unp->machine, machine) == 0) {
1107 if (!unp && (flags & SMB_FLAG_CREATE)) {
1108 unp = malloc(sizeof(*unp));
1109 memset(unp, 0, sizeof(*unp));
1111 unp->nextp = usernamesp;
1112 unp->name = strdup(usern);
1113 unp->machine = strdup(machine);
1115 lock_InitializeMutex(&unp->mx, "username_t mutex");
1117 lock_ReleaseWrite(&smb_rctLock);
1121 smb_user_t *smb_FindUserByNameThisSession(smb_vc_t *vcp, char *usern)
1123 smb_user_t *uidp= NULL;
1125 lock_ObtainWrite(&smb_rctLock);
1126 for(uidp = vcp->usersp; uidp; uidp = uidp->nextp) {
1129 if (stricmp(uidp->unp->name, usern) == 0) {
1131 osi_Log3(smb_logp,"smb_FindUserByNameThisSession vcp[0x%p] uid[%d] match-name[%s]",
1132 vcp,uidp->userID,osi_LogSaveString(smb_logp,usern));
1137 lock_ReleaseWrite(&smb_rctLock);
1140 void smb_ReleaseUID(smb_user_t *uidp)
1147 lock_ObtainWrite(&smb_rctLock);
1148 osi_assert(uidp->refCount-- > 0);
1149 if (uidp->refCount == 0 && (uidp->flags & SMB_USERFLAG_DELETE)) {
1150 lupp = &uidp->vcp->usersp;
1151 for(up = *lupp; up; lupp = &up->nextp, up = *lupp) {
1155 osi_assert(up != NULL);
1157 lock_FinalizeMutex(&uidp->mx);
1159 userp = uidp->unp->userp; /* avoid deadlock by releasing */
1160 uidp->unp->userp = NULL; /* after releasing the lock */
1162 smb_ReleaseVCNoLock(uidp->vcp);
1165 lock_ReleaseWrite(&smb_rctLock);
1167 cm_ReleaseUserVCRef(userp);
1168 cm_ReleaseUser(userp);
1173 /* retrieve a held reference to a user structure corresponding to an incoming
1175 * corresponding release function is cm_ReleaseUser.
1177 cm_user_t *smb_GetUser(smb_vc_t *vcp, smb_packet_t *inp)
1183 smbp = (smb_t *) inp;
1184 uidp = smb_FindUID(vcp, smbp->uid, 0);
1185 if ((!uidp) || (!uidp->unp))
1188 lock_ObtainMutex(&uidp->mx);
1189 up = uidp->unp->userp;
1191 lock_ReleaseMutex(&uidp->mx);
1193 smb_ReleaseUID(uidp);
1199 * Return a pointer to a pathname extracted from a TID structure. The
1200 * TID structure is not held; assume it won't go away.
1202 long smb_LookupTIDPath(smb_vc_t *vcp, unsigned short tid, char ** treepath)
1207 tidp = smb_FindTID(vcp, tid, 0);
1211 if (tidp->flags & SMB_TIDFLAG_IPC) {
1212 code = CM_ERROR_TIDIPC;
1213 /* tidp->pathname would be NULL, but that's fine */
1215 *treepath = tidp->pathname;
1216 smb_ReleaseTID(tidp);
1221 /* check to see if we have a chained fid, that is, a fid that comes from an
1222 * OpenAndX message that ran earlier in this packet. In this case, the fid
1223 * field in a read, for example, request, isn't set, since the value is
1224 * supposed to be inherited from the openAndX call.
1226 int smb_ChainFID(int fid, smb_packet_t *inp)
1228 if (inp->fid == 0 || inp->inCount == 0)
1234 /* are we a priv'd user? What does this mean on NT? */
1235 int smb_SUser(cm_user_t *userp)
1240 /* find a file ID. If we pass in 0 we select an unused File ID.
1241 * If the SMB_FLAG_CREATE flag is set, we allocate a new
1242 * smb_fid_t data structure if desired File ID cannot be found.
1244 smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
1249 if (fid == 0 && !(flags & SMB_FLAG_CREATE))
1252 lock_ObtainWrite(&smb_rctLock);
1253 /* figure out if we need to allocate a new file ID */
1256 fid = vcp->fidCounter;
1260 for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
1261 if (fid == fidp->fid) {
1266 "New FID number wraps on vcp 0x%x", vcp);
1276 if (!fidp && (flags & SMB_FLAG_CREATE)) {
1277 char eventName[MAX_PATH];
1279 sprintf(eventName,"fid_t event vcp=%d fid=%d", vcp->vcID, fid);
1280 event = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
1281 if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
1282 osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
1283 thrd_CloseHandle(event);
1286 osi_Log1(smb_logp, "New FID wraps around for vcp 0x%x", vcp);
1292 fidp = malloc(sizeof(*fidp));
1293 memset(fidp, 0, sizeof(*fidp));
1294 osi_QAdd((osi_queue_t **)&vcp->fidsp, &fidp->q);
1297 smb_HoldVCNoLock(vcp);
1298 lock_InitializeMutex(&fidp->mx, "fid_t mutex");
1300 fidp->curr_chunk = fidp->prev_chunk = -2;
1301 fidp->raw_write_event = event;
1303 vcp->fidCounter = fid+1;
1304 if (vcp->fidCounter == 0) {
1305 osi_Log1(smb_logp, "fidCounter wrapped around for vcp 0x%x",
1307 vcp->fidCounter = 1;
1312 lock_ReleaseWrite(&smb_rctLock);
1316 void smb_ReleaseFID(smb_fid_t *fidp)
1320 smb_vc_t *vcp = NULL;
1321 smb_ioctl_t *ioctlp;
1328 lock_ObtainWrite(&smb_rctLock);
1329 osi_assert(fidp->refCount-- > 0);
1330 if (fidp->refCount == 0 && (fidp->flags & SMB_FID_DELETE)) {
1333 scp = fidp->scp; /* release after lock is released */
1335 userp = fidp->userp;
1338 osi_QRemove((osi_queue_t **) &vcp->fidsp, &fidp->q);
1339 thrd_CloseHandle(fidp->raw_write_event);
1341 /* and see if there is ioctl stuff to free */
1342 ioctlp = fidp->ioctlp;
1345 cm_FreeSpace(ioctlp->prefix);
1346 if (ioctlp->inAllocp)
1347 free(ioctlp->inAllocp);
1348 if (ioctlp->outAllocp)
1349 free(ioctlp->outAllocp);
1355 smb_ReleaseVCNoLock(vcp);
1357 lock_ReleaseWrite(&smb_rctLock);
1359 /* now release the scache structure */
1361 cm_ReleaseSCache(scp);
1364 cm_ReleaseUser(userp);
1368 * Case-insensitive search for one string in another;
1369 * used to find variable names in submount pathnames.
1371 static char *smb_stristr(char *str1, char *str2)
1375 for (cursor = str1; *cursor; cursor++)
1376 if (stricmp(cursor, str2) == 0)
1383 * Substitute a variable value for its name in a submount pathname. Variable
1384 * name has been identified by smb_stristr() and is in substr. Variable name
1385 * length (plus one) is in substr_size. Variable value is in newstr.
1387 static void smb_subst(char *str1, char *substr, unsigned int substr_size,
1392 strcpy(temp, substr + substr_size - 1);
1393 strcpy(substr, newstr);
1397 char VNUserName[] = "%USERNAME%";
1398 char VNLCUserName[] = "%LCUSERNAME%";
1399 char VNComputerName[] = "%COMPUTERNAME%";
1400 char VNLCComputerName[] = "%LCCOMPUTERNAME%";
1403 /* List available shares */
1404 int smb_ListShares()
1408 char shareBuf[4096];
1416 /*strcpy(shareNameList[num_shares], "all");
1417 strcpy(pathNameList[num_shares++], "/afs");*/
1418 fprintf(stderr, "The following shares are available:\n");
1419 fprintf(stderr, "Share Name (AFS Path)\n");
1420 fprintf(stderr, "---------------------\n");
1421 fprintf(stderr, "\\\\%s\\%-16s (%s)\n", smb_localNamep, "ALL", cm_mountRoot);
1424 code = GetWindowsDirectory(sbmtpath, sizeof(sbmtpath));
1425 if (code == 0 || code > sizeof(sbmtpath)) return -1;
1427 strcpy(sbmtpath, cm_confDir);
1429 strcat(sbmtpath, "/afsdsbmt.ini");
1430 len = GetPrivateProfileString("AFS Submounts", NULL, NULL,
1431 shareBuf, sizeof(shareBuf),
1437 this_share = shareBuf;
1441 /*strcpy(shareNameList[num_shares], this_share);*/
1442 len = GetPrivateProfileString("AFS Submounts", this_share,
1449 if (strncmp(p, cm_mountRoot, strlen(cm_mountRoot)) != 0)
1452 if (*p == '\\') *p = '/'; /* change to / */
1456 fprintf(stderr, "\\\\%s\\%-16s (%s%s)\n",
1457 smb_localNamep, this_share, (print_afs ? cm_mountRoot : "\0"),
1460 while (*this_share != 0) this_share++; /* find next NUL */
1461 this_share++; /* skip past the NUL */
1462 } while (*this_share != 0); /* stop at final NUL */
1468 typedef struct smb_findShare_rock {
1472 } smb_findShare_rock_t;
1474 #define SMB_FINDSHARE_EXACT_MATCH 1
1475 #define SMB_FINDSHARE_PARTIAL_MATCH 2
1477 long smb_FindShareProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
1481 smb_findShare_rock_t * vrock = (smb_findShare_rock_t *) rockp;
1482 if (!strnicmp(dep->name, vrock->shareName, 12)) {
1483 if(!stricmp(dep->name, vrock->shareName))
1484 matchType = SMB_FINDSHARE_EXACT_MATCH;
1486 matchType = SMB_FINDSHARE_PARTIAL_MATCH;
1487 if(vrock->match) free(vrock->match);
1488 vrock->match = strdup(dep->name);
1489 vrock->matchType = matchType;
1491 if(matchType == SMB_FINDSHARE_EXACT_MATCH)
1492 return CM_ERROR_STOPNOW;
1498 /* find a shareName in the table of submounts */
1499 int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
1503 char pathName[1024];
1508 char sbmtpath[MAX_PATH];
1513 DWORD allSubmount = 1;
1515 /* if allSubmounts == 0, only return the //mountRoot/all share
1516 * if in fact it has been been created in the subMounts table.
1517 * This is to allow sites that want to restrict access to the
1520 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1521 0, KEY_QUERY_VALUE, &parmKey);
1522 if (code == ERROR_SUCCESS) {
1523 len = sizeof(allSubmount);
1524 code = RegQueryValueEx(parmKey, "AllSubmount", NULL, NULL,
1525 (BYTE *) &allSubmount, &len);
1526 if (code != ERROR_SUCCESS) {
1529 RegCloseKey (parmKey);
1532 if (allSubmount && _stricmp(shareName, "all") == 0) {
1537 /* In case, the all share is disabled we need to still be able
1538 * to handle ioctl requests
1540 if (_stricmp(shareName, "ioctl$") == 0) {
1541 *pathNamep = strdup("/.__ioctl__");
1545 if (_stricmp(shareName, "IPC$") == 0 ||
1546 _stricmp(shareName, SMB_IOCTL_FILENAME_NOSLASH) == 0 ||
1547 _stricmp(shareName, "DESKTOP.INI") == 0
1554 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
1555 0, KEY_QUERY_VALUE, &parmKey);
1556 if (code == ERROR_SUCCESS) {
1557 len = sizeof(pathName);
1558 code = RegQueryValueEx(parmKey, shareName, NULL, NULL,
1559 (BYTE *) pathName, &len);
1560 if (code != ERROR_SUCCESS)
1562 RegCloseKey (parmKey);
1567 strcpy(sbmtpath, cm_confDir);
1568 strcat(sbmtpath, "/afsdsbmt.ini");
1569 len = GetPrivateProfileString("AFS Submounts", shareName, "",
1570 pathName, sizeof(pathName), sbmtpath);
1572 if (len != 0 && len != sizeof(pathName) - 1) {
1573 /* We can accept either unix or PC style AFS pathnames. Convert
1574 * Unix-style to PC style here for internal use.
1577 if (strncmp(p, cm_mountRoot, strlen(cm_mountRoot)) == 0)
1578 p += strlen(cm_mountRoot); /* skip mount path */
1581 if (*q == '/') *q = '\\'; /* change to \ */
1587 if (var = smb_stristr(p, VNUserName)) {
1588 if (uidp && uidp->unp)
1589 smb_subst(p, var, sizeof(VNUserName),uidp->unp->name);
1591 smb_subst(p, var, sizeof(VNUserName)," ");
1593 else if (var = smb_stristr(p, VNLCUserName))
1595 if (uidp && uidp->unp)
1596 strcpy(temp, uidp->unp->name);
1600 smb_subst(p, var, sizeof(VNLCUserName), temp);
1602 else if (var = smb_stristr(p, VNComputerName))
1604 sizeTemp = sizeof(temp);
1605 GetComputerName((LPTSTR)temp, &sizeTemp);
1606 smb_subst(p, var, sizeof(VNComputerName), temp);
1608 else if (var = smb_stristr(p, VNLCComputerName))
1610 sizeTemp = sizeof(temp);
1611 GetComputerName((LPTSTR)temp, &sizeTemp);
1613 smb_subst(p, var, sizeof(VNLCComputerName), temp);
1618 *pathNamep = strdup(p);
1623 /* First lookup shareName in root.afs */
1625 smb_findShare_rock_t vrock;
1627 char * p = shareName;
1630 /* attempt to locate a partial match in root.afs. This is because
1631 when using the ANSI RAP calls, the share name is limited to 13 chars
1632 and hence is truncated. Of course we prefer exact matches. */
1634 thyper.HighPart = 0;
1637 vrock.shareName = shareName;
1639 vrock.matchType = 0;
1641 cm_HoldSCache(cm_data.rootSCachep);
1642 code = cm_ApplyDir(cm_data.rootSCachep, smb_FindShareProc, &vrock, &thyper,
1643 (uidp? (uidp->unp ? uidp->unp->userp : NULL) : NULL), &req, NULL);
1644 cm_ReleaseSCache(cm_data.rootSCachep);
1646 if (vrock.matchType) {
1647 sprintf(pathName,"/%s/",vrock.match);
1648 *pathNamep = strdup(strlwr(pathName));
1653 /* if we get here, there was no match for the share in root.afs */
1654 /* so try to create \\<netbiosName>\<cellname> */
1659 /* Get the full name for this cell */
1660 code = cm_SearchCellFile(p, temp, 0, 0);
1661 #ifdef AFS_AFSDB_ENV
1662 if (code && cm_dnsEnabled) {
1664 code = cm_SearchCellByDNS(p, temp, &ttl, 0, 0);
1667 /* construct the path */
1669 sprintf(pathName,rw ? "/.%s/" : "/%s/",temp);
1670 *pathNamep = strdup(strlwr(pathName));
1679 /* Client-side offline caching policy types */
1680 #define CSC_POLICY_MANUAL 0
1681 #define CSC_POLICY_DOCUMENTS 1
1682 #define CSC_POLICY_PROGRAMS 2
1683 #define CSC_POLICY_DISABLE 3
1685 int smb_FindShareCSCPolicy(char *shareName)
1691 int retval = CSC_POLICY_MANUAL;
1693 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
1694 AFSREG_CLT_OPENAFS_SUBKEY "\\CSCPolicy",
1697 REG_OPTION_NON_VOLATILE,
1703 len = sizeof(policy);
1704 if ( RegQueryValueEx( hkCSCPolicy, shareName, 0, &dwType, policy, &len ) ||
1706 retval = stricmp("all",shareName) ? CSC_POLICY_MANUAL : CSC_POLICY_DISABLE;
1708 else if (stricmp(policy, "documents") == 0)
1710 retval = CSC_POLICY_DOCUMENTS;
1712 else if (stricmp(policy, "programs") == 0)
1714 retval = CSC_POLICY_PROGRAMS;
1716 else if (stricmp(policy, "disable") == 0)
1718 retval = CSC_POLICY_DISABLE;
1721 RegCloseKey(hkCSCPolicy);
1725 /* find a dir search structure by cookie value, and return it held.
1726 * Must be called with smb_globalLock held.
1728 smb_dirSearch_t *smb_FindDirSearchNoLock(long cookie)
1730 smb_dirSearch_t *dsp;
1732 for (dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) {
1733 if (dsp->cookie == cookie) {
1734 if (dsp != smb_firstDirSearchp) {
1735 /* move to head of LRU queue, too, if we're not already there */
1736 if (smb_lastDirSearchp == (smb_dirSearch_t *) &dsp->q)
1737 smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&dsp->q);
1738 osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
1739 osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
1740 if (!smb_lastDirSearchp)
1741 smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
1743 lock_ObtainMutex(&dsp->mx);
1745 lock_ReleaseMutex(&dsp->mx);
1751 osi_Log1(smb_logp,"smb_FindDirSearch(%d) == NULL",cookie);
1752 for (dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) {
1753 osi_Log1(smb_logp,"... valid id: %d", dsp->cookie);
1759 void smb_DeleteDirSearch(smb_dirSearch_t *dsp)
1761 lock_ObtainWrite(&smb_globalLock);
1762 lock_ObtainMutex(&dsp->mx);
1763 dsp->flags |= SMB_DIRSEARCH_DELETE;
1764 if (dsp->scp != NULL) {
1765 lock_ObtainMutex(&dsp->scp->mx);
1766 if (dsp->flags & SMB_DIRSEARCH_BULKST) {
1767 dsp->flags &= ~SMB_DIRSEARCH_BULKST;
1768 dsp->scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
1769 dsp->scp->bulkStatProgress = hones;
1771 lock_ReleaseMutex(&dsp->scp->mx);
1773 lock_ReleaseMutex(&dsp->mx);
1774 lock_ReleaseWrite(&smb_globalLock);
1777 /* Must be called with the smb_globalLock held */
1778 void smb_ReleaseDirSearchNoLock(smb_dirSearch_t *dsp)
1780 cm_scache_t *scp = NULL;
1782 lock_ObtainMutex(&dsp->mx);
1783 osi_assert(dsp->refCount-- > 0);
1784 if (dsp->refCount == 0 && (dsp->flags & SMB_DIRSEARCH_DELETE)) {
1785 if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp)
1786 smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q);
1787 osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
1788 lock_ReleaseMutex(&dsp->mx);
1789 lock_FinalizeMutex(&dsp->mx);
1793 lock_ReleaseMutex(&dsp->mx);
1795 /* do this now to avoid spurious locking hierarchy creation */
1797 cm_ReleaseSCache(scp);
1800 void smb_ReleaseDirSearch(smb_dirSearch_t *dsp)
1802 lock_ObtainWrite(&smb_globalLock);
1803 smb_ReleaseDirSearchNoLock(dsp);
1804 lock_ReleaseWrite(&smb_globalLock);
1807 /* find a dir search structure by cookie value, and return it held */
1808 smb_dirSearch_t *smb_FindDirSearch(long cookie)
1810 smb_dirSearch_t *dsp;
1812 lock_ObtainWrite(&smb_globalLock);
1813 dsp = smb_FindDirSearchNoLock(cookie);
1814 lock_ReleaseWrite(&smb_globalLock);
1818 /* GC some dir search entries, in the address space expected by the specific protocol.
1819 * Must be called with smb_globalLock held; release the lock temporarily.
1821 #define SMB_DIRSEARCH_GCMAX 10 /* how many at once */
1822 void smb_GCDirSearches(int isV3)
1824 smb_dirSearch_t *prevp;
1825 smb_dirSearch_t *tp;
1826 smb_dirSearch_t *victimsp[SMB_DIRSEARCH_GCMAX];
1830 victimCount = 0; /* how many have we got so far */
1831 for (tp = smb_lastDirSearchp; tp; tp=prevp) {
1832 /* we'll move tp from queue, so
1835 prevp = (smb_dirSearch_t *) osi_QPrev(&tp->q);
1836 /* if no one is using this guy, and we're either in the new protocol,
1837 * or we're in the old one and this is a small enough ID to be useful
1838 * to the old protocol, GC this guy.
1840 if (tp->refCount == 0 && (isV3 || tp->cookie <= 255)) {
1841 /* hold and delete */
1842 tp->flags |= SMB_DIRSEARCH_DELETE;
1843 victimsp[victimCount++] = tp;
1847 /* don't do more than this */
1848 if (victimCount >= SMB_DIRSEARCH_GCMAX)
1852 /* now release them */
1853 for (i = 0; i < victimCount; i++) {
1854 smb_ReleaseDirSearchNoLock(victimsp[i]);
1858 /* function for allocating a dir search entry. We need these to remember enough context
1859 * since we don't get passed the path from call to call during a directory search.
1861 * Returns a held dir search structure, and bumps the reference count on the vnode,
1862 * since it saves a pointer to the vnode.
1864 smb_dirSearch_t *smb_NewDirSearch(int isV3)
1866 smb_dirSearch_t *dsp;
1872 lock_ObtainWrite(&smb_globalLock);
1875 /* what's the biggest ID allowed in this version of the protocol */
1876 maxAllowed = isV3 ? 65535 : 255;
1877 if (smb_dirSearchCounter > maxAllowed)
1878 smb_dirSearchCounter = 1;
1880 start = smb_dirSearchCounter;
1883 /* twice so we have enough tries to find guys we GC after one pass;
1884 * 10 extra is just in case I mis-counted.
1886 if (++counter > 2*maxAllowed+10)
1887 osi_panic("afsd: dir search cookie leak", __FILE__, __LINE__);
1889 if (smb_dirSearchCounter > maxAllowed) {
1890 smb_dirSearchCounter = 1;
1892 if (smb_dirSearchCounter == start) {
1894 smb_GCDirSearches(isV3);
1897 dsp = smb_FindDirSearchNoLock(smb_dirSearchCounter);
1899 /* don't need to watch for refcount zero and deleted, since
1900 * we haven't dropped the global lock.
1902 lock_ObtainMutex(&dsp->mx);
1904 lock_ReleaseMutex(&dsp->mx);
1905 ++smb_dirSearchCounter;
1909 dsp = malloc(sizeof(*dsp));
1910 memset(dsp, 0, sizeof(*dsp));
1911 dsp->cookie = smb_dirSearchCounter;
1912 ++smb_dirSearchCounter;
1914 lock_InitializeMutex(&dsp->mx, "cm_dirSearch_t");
1915 dsp->lastTime = osi_Time();
1916 osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
1917 if (!smb_lastDirSearchp)
1918 smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
1921 lock_ReleaseWrite(&smb_globalLock);
1925 static smb_packet_t *GetPacket(void)
1929 unsigned int npar, seg, tb_sel;
1932 lock_ObtainWrite(&smb_globalLock);
1933 tbp = smb_packetFreeListp;
1935 smb_packetFreeListp = tbp->nextp;
1936 lock_ReleaseWrite(&smb_globalLock);
1939 tbp = calloc(65540,1);
1941 tbp = malloc(sizeof(smb_packet_t));
1943 tbp->magic = SMB_PACKETMAGIC;
1946 tbp->resumeCode = 0;
1952 tbp->ncb_length = 0;
1957 npar = SMB_PACKETSIZE >> 4; /* number of paragraphs */
1960 __dpmi_allocate_dos_memory(npar, &tb_sel); /* DOS segment */
1962 osi_Log1(smb_logp, "Cannot allocate %d paragraphs of DOS memory",
1964 osi_panic("",__FILE__,__LINE__);
1967 osi_Log2(smb_logp, "Allocated %d paragraphs of DOS mem at 0x%X",
1972 tbp->dos_pkt = (seg * 16) + 0; /* DOS physical address */
1973 tbp->dos_pkt_sel = tb_sel;
1976 osi_assert(tbp->magic == SMB_PACKETMAGIC);
1981 smb_packet_t *smb_CopyPacket(smb_packet_t *pkt)
1985 memcpy(tbp, pkt, sizeof(smb_packet_t));
1986 tbp->wctp = tbp->data + (unsigned int)(pkt->wctp - pkt->data);
1988 smb_HoldVC(tbp->vcp);
1992 static NCB *GetNCB(void)
1997 unsigned int npar, seg, tb_sel;
2000 lock_ObtainWrite(&smb_globalLock);
2001 tbp = smb_ncbFreeListp;
2003 smb_ncbFreeListp = tbp->nextp;
2004 lock_ReleaseWrite(&smb_globalLock);
2007 tbp = calloc(sizeof(*tbp),1);
2009 tbp = malloc(sizeof(*tbp));
2010 npar = (sizeof(NCB)+15) >> 4; /* number of paragraphs */
2013 __dpmi_allocate_dos_memory(npar, &tb_sel); /* DOS segment */
2015 osi_Log1(smb_logp, "Cannot allocate %d paragraphs of DOS mem in GetNCB",
2017 osi_panic("",__FILE__,__LINE__);
2019 osi_Log2(smb_logp, "Allocated %d paragraphs of DOS mem at 0x%X in GetNCB",
2024 tbp->dos_ncb = (seg * 16) + 0; /* DOS physical address */
2025 tbp->dos_ncb_sel = tb_sel;
2027 tbp->magic = SMB_NCBMAGIC;
2030 osi_assert(tbp->magic == SMB_NCBMAGIC);
2032 memset(&tbp->ncb, 0, sizeof(NCB));
2035 dos_memset(tbp->dos_ncb, 0, sizeof(NCB));
2040 void smb_FreePacket(smb_packet_t *tbp)
2042 smb_vc_t * vcp = NULL;
2043 osi_assert(tbp->magic == SMB_PACKETMAGIC);
2045 lock_ObtainWrite(&smb_globalLock);
2046 tbp->nextp = smb_packetFreeListp;
2047 smb_packetFreeListp = tbp;
2048 tbp->magic = SMB_PACKETMAGIC;
2052 tbp->resumeCode = 0;
2058 tbp->ncb_length = 0;
2060 lock_ReleaseWrite(&smb_globalLock);
2066 static void FreeNCB(NCB *bufferp)
2070 tbp = (smb_ncb_t *) bufferp;
2071 osi_assert(tbp->magic == SMB_NCBMAGIC);
2073 lock_ObtainWrite(&smb_globalLock);
2074 tbp->nextp = smb_ncbFreeListp;
2075 smb_ncbFreeListp = tbp;
2076 lock_ReleaseWrite(&smb_globalLock);
2079 /* get a ptr to the data part of a packet, and its count */
2080 unsigned char *smb_GetSMBData(smb_packet_t *smbp, int *nbytesp)
2084 unsigned char *afterParmsp;
2086 parmBytes = *smbp->wctp << 1;
2087 afterParmsp = smbp->wctp + parmBytes + 1;
2089 dataBytes = afterParmsp[0] + (afterParmsp[1]<<8);
2090 if (nbytesp) *nbytesp = dataBytes;
2092 /* don't forget to skip the data byte count, since it follows
2093 * the parameters; that's where the "2" comes from below.
2095 return (unsigned char *) (afterParmsp + 2);
2098 /* must set all the returned parameters before playing around with the
2099 * data region, since the data region is located past the end of the
2100 * variable number of parameters.
2102 void smb_SetSMBDataLength(smb_packet_t *smbp, unsigned int dsize)
2104 unsigned char *afterParmsp;
2106 afterParmsp = smbp->wctp + ((*smbp->wctp)<<1) + 1;
2108 *afterParmsp++ = dsize & 0xff;
2109 *afterParmsp = (dsize>>8) & 0xff;
2112 /* return the parm'th parameter in the smbp packet */
2113 unsigned int smb_GetSMBParm(smb_packet_t *smbp, int parm)
2116 unsigned char *parmDatap;
2118 parmCount = *smbp->wctp;
2120 if (parm >= parmCount) {
2123 sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
2124 parm, parmCount, smbp->ncb_length);
2125 osi_Log3(smb_logp,"Bad SMB param %d out of %d, ncb len %d",
2126 parm, parmCount, smbp->ncb_length);
2128 LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM,
2129 __FILE__, __LINE__, parm, parmCount, smbp->ncb_length);
2131 osi_panic(s, __FILE__, __LINE__);
2133 parmDatap = smbp->wctp + (2*parm) + 1;
2135 return parmDatap[0] + (parmDatap[1] << 8);
2138 /* return the parm'th parameter in the smbp packet */
2139 unsigned int smb_GetSMBOffsetParm(smb_packet_t *smbp, int parm, int offset)
2142 unsigned char *parmDatap;
2144 parmCount = *smbp->wctp;
2146 if (parm * 2 + offset >= parmCount * 2) {
2149 sprintf(s, "Bad SMB param %d offset %d out of %d, ncb len %d",
2150 parm, offset, parmCount, smbp->ncb_length);
2152 LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM_WITH_OFFSET,
2153 __FILE__, __LINE__, parm, offset, parmCount, smbp->ncb_length);
2155 osi_Log4(smb_logp, "Bad SMB param %d offset %d out of %d, ncb len %d",
2156 parm, offset, parmCount, smbp->ncb_length);
2157 osi_panic(s, __FILE__, __LINE__);
2159 parmDatap = smbp->wctp + (2*parm) + 1 + offset;
2161 return parmDatap[0] + (parmDatap[1] << 8);
2164 void smb_SetSMBParm(smb_packet_t *smbp, int slot, unsigned int parmValue)
2168 /* make sure we have enough slots */
2169 if (*smbp->wctp <= slot)
2170 *smbp->wctp = slot+1;
2172 parmDatap = smbp->wctp + 2*slot + 1 + smbp->oddByte;
2173 *parmDatap++ = parmValue & 0xff;
2174 *parmDatap = (parmValue>>8) & 0xff;
2177 void smb_SetSMBParmLong(smb_packet_t *smbp, int slot, unsigned int parmValue)
2181 /* make sure we have enough slots */
2182 if (*smbp->wctp <= slot)
2183 *smbp->wctp = slot+2;
2185 parmDatap = smbp->wctp + 2*slot + 1 + smbp->oddByte;
2186 *parmDatap++ = parmValue & 0xff;
2187 *parmDatap++ = (parmValue>>8) & 0xff;
2188 *parmDatap++ = (parmValue>>16) & 0xff;
2189 *parmDatap++ = (parmValue>>24) & 0xff;
2192 void smb_SetSMBParmDouble(smb_packet_t *smbp, int slot, char *parmValuep)
2197 /* make sure we have enough slots */
2198 if (*smbp->wctp <= slot)
2199 *smbp->wctp = slot+4;
2201 parmDatap = smbp->wctp + 2*slot + 1 + smbp->oddByte;
2203 *parmDatap++ = *parmValuep++;
2206 void smb_SetSMBParmByte(smb_packet_t *smbp, int slot, unsigned int parmValue)
2210 /* make sure we have enough slots */
2211 if (*smbp->wctp <= slot) {
2212 if (smbp->oddByte) {
2214 *smbp->wctp = slot+1;
2219 parmDatap = smbp->wctp + 2*slot + 1 + (1 - smbp->oddByte);
2220 *parmDatap++ = parmValue & 0xff;
2223 void smb_StripLastComponent(char *outPathp, char **lastComponentp, char *inPathp)
2227 lastSlashp = strrchr(inPathp, '\\');
2229 *lastComponentp = lastSlashp;
2232 if (inPathp == lastSlashp)
2234 *outPathp++ = *inPathp++;
2243 unsigned char *smb_ParseASCIIBlock(unsigned char *inp, char **chainpp)
2248 *chainpp = inp + strlen(inp) + 1; /* skip over null-terminated string */
2253 unsigned char *smb_ParseVblBlock(unsigned char *inp, char **chainpp, int *lengthp)
2259 tlen = inp[0] + (inp[1]<<8);
2260 inp += 2; /* skip length field */
2263 *chainpp = inp + tlen;
2272 /* format a packet as a response */
2273 void smb_FormatResponsePacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *op)
2278 outp = (smb_t *) op;
2280 /* zero the basic structure through the smb_wct field, and zero the data
2281 * size field, assuming that wct stays zero; otherwise, you have to
2282 * explicitly set the data size field, too.
2284 inSmbp = (smb_t *) inp;
2285 memset(outp, 0, sizeof(smb_t)+2);
2291 outp->com = inSmbp->com;
2292 outp->tid = inSmbp->tid;
2293 outp->pid = inSmbp->pid;
2294 outp->uid = inSmbp->uid;
2295 outp->mid = inSmbp->mid;
2296 outp->res[0] = inSmbp->res[0];
2297 outp->res[1] = inSmbp->res[1];
2298 op->inCom = inSmbp->com;
2300 outp->reb = SMB_FLAGS_SERVER_TO_CLIENT | SMB_FLAGS_CANONICAL_PATHNAMES;
2301 outp->flg2 = SMB_FLAGS2_KNOWS_LONG_NAMES;
2303 /* copy fields in generic packet area */
2304 op->wctp = &outp->wct;
2307 /* send a (probably response) packet; vcp tells us to whom to send it.
2308 * we compute the length by looking at wct and bcc fields.
2310 void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp)
2327 dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
2330 memset((char *)ncbp, 0, sizeof(NCB));
2332 extra = 2 * (*inp->wctp); /* space used by parms, in bytes */
2333 tp = inp->wctp + 1+ extra; /* points to count of data bytes */
2334 extra += tp[0] + (tp[1]<<8);
2335 extra += (unsigned int)(inp->wctp - inp->data); /* distance to last wct field */
2336 extra += 3; /* wct and length fields */
2338 ncbp->ncb_length = extra; /* bytes to send */
2339 ncbp->ncb_lsn = (unsigned char) vcp->lsn; /* vc to use */
2340 ncbp->ncb_lana_num = vcp->lana;
2341 ncbp->ncb_command = NCBSEND; /* op means send data */
2343 ncbp->ncb_buffer = (char *) inp;/* packet */
2344 code = Netbios(ncbp);
2346 ncbp->ncb_buffer = inp->dos_pkt;/* packet */
2347 ((smb_ncb_t*)ncbp)->orig_pkt = inp;
2349 /* copy header information from virtual to DOS address space */
2350 dosmemput((char*)inp, SMB_PACKETSIZE, inp->dos_pkt);
2351 code = Netbios(ncbp, dos_ncb);
2357 case 0x01: s = "llegal buffer length "; break;
2358 case 0x03: s = "illegal command "; break;
2359 case 0x05: s = "command timed out "; break;
2360 case 0x06: s = "message incomplete, issue another command"; break;
2361 case 0x07: s = "illegal buffer address "; break;
2362 case 0x08: s = "session number out of range "; break;
2363 case 0x09: s = "no resource available "; break;
2364 case 0x0a: s = "session closed "; break;
2365 case 0x0b: s = "command cancelled "; break;
2366 case 0x0d: s = "duplicate name "; break;
2367 case 0x0e: s = "name table full "; break;
2368 case 0x0f: s = "no deletions, name has active sessions "; break;
2369 case 0x11: s = "local session table full "; break;
2370 case 0x12: s = "remote session table full "; break;
2371 case 0x13: s = "illegal name number "; break;
2372 case 0x14: s = "no callname "; break;
2373 case 0x15: s = "cannot put * in NCB_NAME "; break;
2374 case 0x16: s = "name in use on remote adapter "; break;
2375 case 0x17: s = "name deleted "; break;
2376 case 0x18: s = "session ended abnormally "; break;
2377 case 0x19: s = "name conflict detected "; break;
2378 case 0x21: s = "interface busy, IRET before retrying "; break;
2379 case 0x22: s = "too many commands outstanding, retry later"; break;
2380 case 0x23: s = "ncb_lana_num field invalid "; break;
2381 case 0x24: s = "command completed while cancel occurring "; break;
2382 case 0x26: s = "command not valid to cancel "; break;
2383 case 0x30: s = "name defined by anther local process "; break;
2384 case 0x34: s = "environment undefined. RESET required "; break;
2385 case 0x35: s = "required OS resources exhausted "; break;
2386 case 0x36: s = "max number of applications exceeded "; break;
2387 case 0x37: s = "no saps available for netbios "; break;
2388 case 0x38: s = "requested resources are not available "; break;
2389 case 0x39: s = "invalid ncb address or length > segment "; break;
2390 case 0x3B: s = "invalid NCB DDID "; break;
2391 case 0x3C: s = "lock of user area failed "; break;
2392 case 0x3f: s = "NETBIOS not loaded "; break;
2393 case 0x40: s = "system error "; break;
2395 s = "unknown error";
2397 osi_Log2(smb_logp, "SendPacket failure code %d \"%s\"", code, s);
2404 void smb_MapNTError(long code, unsigned long *NTStatusp)
2406 unsigned long NTStatus;
2408 /* map CM_ERROR_* errors to NT 32-bit status codes */
2409 /* NT Status codes are listed in ntstatus.h not winerror.h */
2410 if (code == CM_ERROR_NOSUCHCELL) {
2411 NTStatus = 0xC000000FL; /* No such file */
2413 else if (code == CM_ERROR_NOSUCHVOLUME) {
2414 NTStatus = 0xC000000FL; /* No such file */
2416 else if (code == CM_ERROR_TIMEDOUT) {
2418 NTStatus = 0xC00000CFL; /* Sharing Paused */
2420 NTStatus = 0x00000102L; /* Timeout */
2423 else if (code == CM_ERROR_RETRY) {
2424 NTStatus = 0xC000022DL; /* Retry */
2426 else if (code == CM_ERROR_NOACCESS) {
2427 NTStatus = 0xC0000022L; /* Access denied */
2429 else if (code == CM_ERROR_READONLY) {
2430 NTStatus = 0xC00000A2L; /* Write protected */
2432 else if (code == CM_ERROR_NOSUCHFILE) {
2433 NTStatus = 0xC000000FL; /* No such file */
2435 else if (code == CM_ERROR_NOSUCHPATH) {
2436 NTStatus = 0xC000003AL; /* Object path not found */
2438 else if (code == CM_ERROR_TOOBIG) {
2439 NTStatus = 0xC000007BL; /* Invalid image format */
2441 else if (code == CM_ERROR_INVAL) {
2442 NTStatus = 0xC000000DL; /* Invalid parameter */
2444 else if (code == CM_ERROR_BADFD) {
2445 NTStatus = 0xC0000008L; /* Invalid handle */
2447 else if (code == CM_ERROR_BADFDOP) {
2448 NTStatus = 0xC0000022L; /* Access denied */
2450 else if (code == CM_ERROR_EXISTS) {
2451 NTStatus = 0xC0000035L; /* Object name collision */
2453 else if (code == CM_ERROR_NOTEMPTY) {
2454 NTStatus = 0xC0000101L; /* Directory not empty */
2456 else if (code == CM_ERROR_CROSSDEVLINK) {
2457 NTStatus = 0xC00000D4L; /* Not same device */
2459 else if (code == CM_ERROR_NOTDIR) {
2460 NTStatus = 0xC0000103L; /* Not a directory */
2462 else if (code == CM_ERROR_ISDIR) {
2463 NTStatus = 0xC00000BAL; /* File is a directory */
2465 else if (code == CM_ERROR_BADOP) {
2467 /* I have no idea where this comes from */
2468 NTStatus = 0xC09820FFL; /* SMB no support */
2470 NTStatus = 0xC00000BBL; /* Not supported */
2471 #endif /* COMMENT */
2473 else if (code == CM_ERROR_BADSHARENAME) {
2474 NTStatus = 0xC00000CCL; /* Bad network name */
2476 else if (code == CM_ERROR_NOIPC) {
2478 NTStatus = 0xC0000022L; /* Access Denied */
2480 NTStatus = 0xC000013DL; /* Remote Resources */
2483 else if (code == CM_ERROR_CLOCKSKEW) {
2484 NTStatus = 0xC0000133L; /* Time difference at DC */
2486 else if (code == CM_ERROR_BADTID) {
2487 NTStatus = 0xC0982005L; /* SMB bad TID */
2489 else if (code == CM_ERROR_USESTD) {
2490 NTStatus = 0xC09820FBL; /* SMB use standard */
2492 else if (code == CM_ERROR_QUOTA) {
2494 NTStatus = 0xC0000044L; /* Quota exceeded */
2496 NTStatus = 0xC000007FL; /* Disk full */
2499 else if (code == CM_ERROR_SPACE) {
2500 NTStatus = 0xC000007FL; /* Disk full */
2502 else if (code == CM_ERROR_ATSYS) {
2503 NTStatus = 0xC0000033L; /* Object name invalid */
2505 else if (code == CM_ERROR_BADNTFILENAME) {
2506 NTStatus = 0xC0000033L; /* Object name invalid */
2508 else if (code == CM_ERROR_WOULDBLOCK) {
2509 NTStatus = 0xC0000055L; /* Lock not granted */
2511 else if (code == CM_ERROR_SHARING_VIOLATION) {
2512 NTStatus = 0xC0000043L; /* Sharing violation */
2514 else if (code == CM_ERROR_LOCK_CONFLICT) {
2515 NTStatus = 0xC0000054L; /* Lock conflict */
2517 else if (code == CM_ERROR_PARTIALWRITE) {
2518 NTStatus = 0xC000007FL; /* Disk full */
2520 else if (code == CM_ERROR_BUFFERTOOSMALL) {
2521 NTStatus = 0xC0000023L; /* Buffer too small */
2523 else if (code == CM_ERROR_AMBIGUOUS_FILENAME) {
2524 NTStatus = 0xC0000035L; /* Object name collision */
2526 else if (code == CM_ERROR_BADPASSWORD) {
2527 NTStatus = 0xC000006DL; /* unknown username or bad password */
2529 else if (code == CM_ERROR_BADLOGONTYPE) {
2530 NTStatus = 0xC000015BL; /* logon type not granted */
2532 else if (code == CM_ERROR_GSSCONTINUE) {
2533 NTStatus = 0xC0000016L; /* more processing required */
2535 else if (code == CM_ERROR_TOO_MANY_SYMLINKS) {
2537 NTStatus = 0xC0000280L; /* reparse point not resolved */
2539 NTStatus = 0xC0000022L; /* Access Denied */
2542 else if (code == CM_ERROR_PATH_NOT_COVERED) {
2543 NTStatus = 0xC0000257L; /* Path Not Covered */
2546 else if (code == CM_ERROR_ALLBUSY) {
2547 NTStatus = 0xC00000BFL; /* Network Busy */
2549 else if (code == CM_ERROR_ALLOFFLINE || code == CM_ERROR_ALLDOWN) {
2550 NTStatus = 0xC0000350L; /* Remote Host Down */
2553 /* we do not want to be telling the SMB/CIFS client that
2554 * the AFS Client Service is busy or down.
2556 else if (code == CM_ERROR_ALLBUSY ||
2557 code == CM_ERROR_ALLOFFLINE ||
2558 code == CM_ERROR_ALLDOWN) {
2559 NTStatus = 0xC00000BEL; /* Bad Network Path */
2562 else if (code == RXKADUNKNOWNKEY) {
2563 NTStatus = 0xC0000322L; /* Bad Kerberos key */
2565 NTStatus = 0xC0982001L; /* SMB non-specific error */
2568 *NTStatusp = NTStatus;
2569 osi_Log2(smb_logp, "SMB SEND code %lX as NT %lX", code, NTStatus);
2572 void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep,
2573 unsigned char *classp)
2575 unsigned char class;
2576 unsigned short error;
2578 /* map CM_ERROR_* errors to SMB errors */
2579 if (code == CM_ERROR_NOSUCHCELL) {
2581 error = 3; /* bad path */
2583 else if (code == CM_ERROR_NOSUCHVOLUME) {
2585 error = 3; /* bad path */
2587 else if (code == CM_ERROR_TIMEDOUT) {
2589 error = 81; /* server is paused */
2591 else if (code == CM_ERROR_RETRY) {
2592 class = 2; /* shouldn't happen */
2595 else if (code == CM_ERROR_NOACCESS) {
2597 error = 4; /* bad access */
2599 else if (code == CM_ERROR_READONLY) {
2601 error = 19; /* read only */
2603 else if (code == CM_ERROR_NOSUCHFILE) {
2605 error = 2; /* ENOENT! */
2607 else if (code == CM_ERROR_NOSUCHPATH) {
2609 error = 3; /* Bad path */
2611 else if (code == CM_ERROR_TOOBIG) {
2613 error = 11; /* bad format */
2615 else if (code == CM_ERROR_INVAL) {
2616 class = 2; /* server non-specific error code */
2619 else if (code == CM_ERROR_BADFD) {
2621 error = 6; /* invalid file handle */
2623 else if (code == CM_ERROR_BADFDOP) {
2624 class = 1; /* invalid op on FD */
2627 else if (code == CM_ERROR_EXISTS) {
2629 error = 80; /* file already exists */
2631 else if (code == CM_ERROR_NOTEMPTY) {
2633 error = 5; /* delete directory not empty */
2635 else if (code == CM_ERROR_CROSSDEVLINK) {
2637 error = 17; /* EXDEV */
2639 else if (code == CM_ERROR_NOTDIR) {
2640 class = 1; /* bad path */
2643 else if (code == CM_ERROR_ISDIR) {
2644 class = 1; /* access denied; DOS doesn't have a good match */
2647 else if (code == CM_ERROR_BADOP) {
2651 else if (code == CM_ERROR_BADSHARENAME) {
2655 else if (code == CM_ERROR_NOIPC) {
2657 error = 4; /* bad access */
2659 else if (code == CM_ERROR_CLOCKSKEW) {
2660 class = 1; /* invalid function */
2663 else if (code == CM_ERROR_BADTID) {
2667 else if (code == CM_ERROR_USESTD) {
2671 else if (code == CM_ERROR_REMOTECONN) {
2675 else if (code == CM_ERROR_QUOTA) {
2676 if (vcp->flags & SMB_VCFLAG_USEV3) {
2678 error = 39; /* disk full */
2682 error = 5; /* access denied */
2685 else if (code == CM_ERROR_SPACE) {
2686 if (vcp->flags & SMB_VCFLAG_USEV3) {
2688 error = 39; /* disk full */
2692 error = 5; /* access denied */
2695 else if (code == CM_ERROR_PARTIALWRITE) {
2697 error = 39; /* disk full */
2699 else if (code == CM_ERROR_ATSYS) {
2701 error = 2; /* ENOENT */
2703 else if (code == CM_ERROR_WOULDBLOCK) {
2705 error = 33; /* lock conflict */
2707 else if (code == CM_ERROR_LOCK_CONFLICT) {
2709 error = 33; /* lock conflict */
2711 else if (code == CM_ERROR_SHARING_VIOLATION) {
2713 error = 33; /* lock conflict */
2715 else if (code == CM_ERROR_NOFILES) {
2717 error = 18; /* no files in search */
2719 else if (code == CM_ERROR_RENAME_IDENTICAL) {
2721 error = 183; /* Samba uses this */
2723 else if (code == CM_ERROR_BADPASSWORD || code == CM_ERROR_BADLOGONTYPE) {
2724 /* we don't have a good way of reporting CM_ERROR_BADLOGONTYPE */
2726 error = 2; /* bad password */
2728 else if (code == CM_ERROR_PATH_NOT_COVERED) {
2730 error = 3; /* bad path */
2739 osi_Log3(smb_logp, "SMB SEND code %lX as SMB %d: %d", code, class, error);
2742 long smb_SendCoreBadOp(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
2744 osi_Log0(smb_logp,"SendCoreBadOp - NOT_SUPPORTED");
2745 return CM_ERROR_BADOP;
2748 long smb_ReceiveCoreEcho(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
2750 unsigned short EchoCount, i;
2751 char *data, *outdata;
2754 EchoCount = (unsigned short) smb_GetSMBParm(inp, 0);
2756 for (i=1; i<=EchoCount; i++) {
2757 data = smb_GetSMBData(inp, &dataSize);
2758 smb_SetSMBParm(outp, 0, i);
2759 smb_SetSMBDataLength(outp, dataSize);
2760 outdata = smb_GetSMBData(outp, NULL);
2761 memcpy(outdata, data, dataSize);
2762 smb_SendPacket(vcp, outp);
2768 long smb_ReceiveCoreReadRaw(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
2771 long count, minCount, finalCount;
2776 cm_user_t *userp = NULL;
2780 char *rawBuf = NULL;
2782 dos_ptr rawBuf = NULL;
2789 fd = smb_GetSMBParm(inp, 0);
2790 count = smb_GetSMBParm(inp, 3);
2791 minCount = smb_GetSMBParm(inp, 4);
2792 offset.HighPart = 0; /* too bad */
2793 offset.LowPart = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
2795 osi_Log3(smb_logp, "smb_ReceieveCoreReadRaw fd %d, off 0x%x, size 0x%x",
2796 fd, offset.LowPart, count);
2798 fidp = smb_FindFID(vcp, fd, 0);
2802 pid = ((smb_t *) inp)->pid;
2804 LARGE_INTEGER LOffset, LLength;
2807 key = cm_GenerateKey(vcp->vcID, pid, fd);
2809 LOffset.HighPart = 0;
2810 LOffset.LowPart = offset.LowPart;
2811 LLength.HighPart = 0;
2812 LLength.LowPart = count;
2814 lock_ObtainMutex(&fidp->scp->mx);
2815 code = cm_LockCheckRead(fidp->scp, LOffset, LLength, key);
2816 lock_ReleaseMutex(&fidp->scp->mx);
2822 lock_ObtainMutex(&smb_RawBufLock);
2824 /* Get a raw buf, from head of list */
2825 rawBuf = smb_RawBufs;
2827 smb_RawBufs = *(char **)smb_RawBufs;
2829 smb_RawBufs = _farpeekl(_dos_ds, smb_RawBufs);
2832 lock_ReleaseMutex(&smb_RawBufLock);
2836 if (fidp->flags & SMB_FID_IOCTL)
2839 rc = smb_IoctlReadRaw(fidp, vcp, inp, outp);
2841 rc = smb_IoctlReadRaw(fidp, vcp, inp, outp, rawBuf);
2844 /* Give back raw buffer */
2845 lock_ObtainMutex(&smb_RawBufLock);
2847 *((char **) rawBuf) = smb_RawBufs;
2849 _farpokel(_dos_ds, rawBuf, smb_RawBufs);
2852 smb_RawBufs = rawBuf;
2853 lock_ReleaseMutex(&smb_RawBufLock);
2856 smb_ReleaseFID(fidp);
2860 userp = smb_GetUser(vcp, inp);
2863 code = smb_ReadData(fidp, &offset, count, rawBuf, userp, &finalCount);
2865 /* have to give ReadData flag so it will treat buffer as DOS mem. */
2866 code = smb_ReadData(fidp, &offset, count, (unsigned char *)rawBuf,
2867 userp, &finalCount, TRUE /* rawFlag */);
2874 cm_ReleaseUser(userp);
2877 smb_ReleaseFID(fidp);
2882 dos_ncb = ((smb_ncb_t *)ncbp)->dos_ncb;
2884 memset((char *)ncbp, 0, sizeof(NCB));
2886 ncbp->ncb_length = (unsigned short) finalCount;
2887 ncbp->ncb_lsn = (unsigned char) vcp->lsn;
2888 ncbp->ncb_lana_num = vcp->lana;
2889 ncbp->ncb_command = NCBSEND;
2890 ncbp->ncb_buffer = rawBuf;
2893 code = Netbios(ncbp);
2895 code = Netbios(ncbp, dos_ncb);
2898 osi_Log1(smb_logp, "ReadRaw send failure code %d", code);
2901 /* Give back raw buffer */
2902 lock_ObtainMutex(&smb_RawBufLock);
2904 *((char **) rawBuf) = smb_RawBufs;
2906 _farpokel(_dos_ds, rawBuf, smb_RawBufs);
2909 smb_RawBufs = rawBuf;
2910 lock_ReleaseMutex(&smb_RawBufLock);
2916 long smb_ReceiveCoreLockRecord(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
2918 osi_Log1(smb_logp, "SMB receive core lock record (not implemented); %d + 1 ongoing ops",
2923 long smb_ReceiveCoreUnlockRecord(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
2925 osi_Log1(smb_logp, "SMB receive core unlock record (not implemented); %d + 1 ongoing ops",
2930 long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
2937 int protoIndex; /* index we're using */
2942 char protocol_array[10][1024]; /* protocol signature of the client */
2943 int caps; /* capabilities */
2946 TIME_ZONE_INFORMATION tzi;
2948 osi_Log1(smb_logp, "SMB receive negotiate; %d + 1 ongoing ops",
2952 DWORD now = GetCurrentTime();
2953 if (now - last_msg_time >= 30000
2954 && now - last_msg_time <= 90000) {
2956 "Setting dead_vcp %x", active_vcp);
2958 smb_ReleaseVC(dead_vcp);
2960 "Previous dead_vcp %x", dead_vcp);
2962 smb_HoldVC(active_vcp);
2963 dead_vcp = active_vcp;
2964 dead_vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
2969 inp->flags |= SMB_PACKETFLAG_PROFILE_UPDATE_OK;
2971 namep = smb_GetSMBData(inp, &dbytes);
2974 coreProtoIndex = -1; /* not found */
2977 while(namex < dbytes) {
2978 osi_Log1(smb_logp, "Protocol %s",
2979 osi_LogSaveString(smb_logp, namep+1));
2980 strcpy(protocol_array[tcounter], namep+1);
2982 /* namep points at the first protocol, or really, a 0x02
2983 * byte preceding the null-terminated ASCII name.
2985 if (strcmp("PC NETWORK PROGRAM 1.0", namep+1) == 0) {
2986 coreProtoIndex = tcounter;
2988 else if (smb_useV3 && strcmp("LM1.2X002", namep+1) == 0) {
2989 v3ProtoIndex = tcounter;
2991 else if (smb_useV3 && strcmp("NT LM 0.12", namep+1) == 0) {
2992 NTProtoIndex = tcounter;
2995 /* compute size of protocol entry */
2996 entryLength = (int)strlen(namep+1);
2997 entryLength += 2; /* 0x02 bytes and null termination */
2999 /* advance over this protocol entry */
3000 namex += entryLength;
3001 namep += entryLength;
3002 tcounter++; /* which proto entry we're looking at */
3005 if (NTProtoIndex != -1) {
3006 protoIndex = NTProtoIndex;
3007 vcp->flags |= (SMB_VCFLAG_USENT | SMB_VCFLAG_USEV3);
3009 else if (v3ProtoIndex != -1) {
3010 protoIndex = v3ProtoIndex;
3011 vcp->flags |= SMB_VCFLAG_USEV3;
3013 else if (coreProtoIndex != -1) {
3014 protoIndex = coreProtoIndex;
3015 vcp->flags |= SMB_VCFLAG_USECORE;
3017 else protoIndex = -1;
3019 if (protoIndex == -1)
3020 return CM_ERROR_INVAL;
3021 else if (NTProtoIndex != -1) {
3022 smb_SetSMBParm(outp, 0, protoIndex);
3023 if (smb_authType != SMB_AUTH_NONE) {
3024 smb_SetSMBParmByte(outp, 1,
3025 NEGOTIATE_SECURITY_USER_LEVEL |
3026 NEGOTIATE_SECURITY_CHALLENGE_RESPONSE); /* user level security, challenge response */
3028 smb_SetSMBParmByte(outp, 1, 0); /* share level auth with plaintext password. */
3030 smb_SetSMBParm(outp, 1, smb_maxMpxRequests); /* max multiplexed requests */
3031 smb_SetSMBParm(outp, 2, smb_maxVCPerServer); /* max VCs per consumer/server connection */
3032 smb_SetSMBParmLong(outp, 3, SMB_PACKETSIZE); /* xmit buffer size */
3033 smb_SetSMBParmLong(outp, 5, SMB_MAXRAWSIZE); /* raw buffer size */
3034 /* The session key is not a well documented field however most clients
3035 * will echo back the session key to the server. Currently we are using
3036 * the same value for all sessions. We should generate a random value
3037 * and store it into the vcp
3039 smb_SetSMBParm(outp, 7, 1); /* next 2: session key */
3040 smb_SetSMBParm(outp, 8, 1);
3042 * Tried changing the capabilities to support for W2K - defect 117695
3043 * Maybe something else needs to be changed here?
3047 smb_SetSMBParmLong(outp, 9, 0x43fd);
3049 smb_SetSMBParmLong(outp, 9, 0x251);
3052 * 32-bit error codes *
3057 caps = NTNEGOTIATE_CAPABILITY_NTSTATUS |
3059 NTNEGOTIATE_CAPABILITY_DFS |
3061 NTNEGOTIATE_CAPABILITY_NTFIND |
3062 NTNEGOTIATE_CAPABILITY_RAWMODE |
3063 NTNEGOTIATE_CAPABILITY_NTSMB;
3065 if ( smb_authType == SMB_AUTH_EXTENDED )
3066 caps |= NTNEGOTIATE_CAPABILITY_EXTENDED_SECURITY;
3068 smb_SetSMBParmLong(outp, 9, caps);
3070 smb_SearchTimeFromUnixTime(&dosTime, unixTime);
3071 smb_SetSMBParmLong(outp, 11, LOWORD(dosTime));/* server time */
3072 smb_SetSMBParmLong(outp, 13, HIWORD(dosTime));/* server date */
3074 GetTimeZoneInformation(&tzi);
3075 smb_SetSMBParm(outp, 15, (unsigned short) tzi.Bias); /* server tzone */
3077 if (smb_authType == SMB_AUTH_NTLM) {
3078 smb_SetSMBParmByte(outp, 16, MSV1_0_CHALLENGE_LENGTH);/* Encryption key length */
3079 smb_SetSMBDataLength(outp, MSV1_0_CHALLENGE_LENGTH + smb_ServerDomainNameLength);
3080 /* paste in encryption key */
3081 datap = smb_GetSMBData(outp, NULL);
3082 memcpy(datap,vcp->encKey,MSV1_0_CHALLENGE_LENGTH);
3083 /* and the faux domain name */
3084 strcpy(datap + MSV1_0_CHALLENGE_LENGTH,smb_ServerDomainName);
3085 } else if ( smb_authType == SMB_AUTH_EXTENDED ) {
3089 smb_SetSMBParmByte(outp, 16, 0); /* Encryption key length */
3091 smb_NegotiateExtendedSecurity(&secBlob, &secBlobLength);
3093 smb_SetSMBDataLength(outp, secBlobLength + sizeof(smb_ServerGUID));
3095 datap = smb_GetSMBData(outp, NULL);
3096 memcpy(datap, &smb_ServerGUID, sizeof(smb_ServerGUID));
3099 datap += sizeof(smb_ServerGUID);
3100 memcpy(datap, secBlob, secBlobLength);
3104 smb_SetSMBParmByte(outp, 16, 0); /* Encryption key length */
3105 smb_SetSMBDataLength(outp, 0); /* Perhaps we should specify 8 bytes anyway */
3108 else if (v3ProtoIndex != -1) {
3109 smb_SetSMBParm(outp, 0, protoIndex);
3111 /* NOTE: Extended authentication cannot be negotiated with v3
3112 * therefore we fail over to NTLM
3114 if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
3115 smb_SetSMBParm(outp, 1,
3116 NEGOTIATE_SECURITY_USER_LEVEL |
3117 NEGOTIATE_SECURITY_CHALLENGE_RESPONSE); /* user level security, challenge response */
3119 smb_SetSMBParm(outp, 1, 0); /* share level auth with clear password */
3121 smb_SetSMBParm(outp, 2, SMB_PACKETSIZE);
3122 smb_SetSMBParm(outp, 3, smb_maxMpxRequests); /* max multiplexed requests */
3123 smb_SetSMBParm(outp, 4, smb_maxVCPerServer); /* max VCs per consumer/server connection */
3124 smb_SetSMBParm(outp, 5, 0); /* no support of block mode for read or write */
3125 smb_SetSMBParm(outp, 6, 1); /* next 2: session key */
3126 smb_SetSMBParm(outp, 7, 1);
3128 smb_SearchTimeFromUnixTime(&dosTime, unixTime);
3129 smb_SetSMBParm(outp, 8, LOWORD(dosTime)); /* server time */
3130 smb_SetSMBParm(outp, 9, HIWORD(dosTime)); /* server date */
3132 GetTimeZoneInformation(&tzi);
3133 smb_SetSMBParm(outp, 10, (unsigned short) tzi.Bias); /* server tzone */
3135 /* NOTE: Extended authentication cannot be negotiated with v3
3136 * therefore we fail over to NTLM
3138 if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
3139 smb_SetSMBParm(outp, 11, MSV1_0_CHALLENGE_LENGTH); /* encryption key length */
3140 smb_SetSMBParm(outp, 12, 0); /* resvd */
3141 smb_SetSMBDataLength(outp, MSV1_0_CHALLENGE_LENGTH + smb_ServerDomainNameLength); /* perhaps should specify 8 bytes anyway */
3142 datap = smb_GetSMBData(outp, NULL);
3143 /* paste in a new encryption key */
3144 memcpy(datap, vcp->encKey, MSV1_0_CHALLENGE_LENGTH);
3145 /* and the faux domain name */
3146 strcpy(datap + MSV1_0_CHALLENGE_LENGTH, smb_ServerDomainName);
3148 smb_SetSMBParm(outp, 11, 0); /* encryption key length */
3149 smb_SetSMBParm(outp, 12, 0); /* resvd */
3150 smb_SetSMBDataLength(outp, 0);
3153 else if (coreProtoIndex != -1) { /* not really supported anymore */
3154 smb_SetSMBParm(outp, 0, protoIndex);
3155 smb_SetSMBDataLength(outp, 0);
3160 void smb_Daemon(void *parmp)
3162 afs_uint32 count = 0;
3164 while(smbShutdownFlag == 0) {
3168 if (smbShutdownFlag == 1)
3171 if ((count % 72) == 0) { /* every five minutes */
3173 time_t old_localZero = smb_localZero;
3175 /* Initialize smb_localZero */
3176 myTime.tm_isdst = -1; /* compute whether on DST or not */
3177 myTime.tm_year = 70;
3183 smb_localZero = mktime(&myTime);
3185 #ifndef USE_NUMERIC_TIME_CONV
3186 smb_CalculateNowTZ();
3187 #endif /* USE_NUMERIC_TIME_CONV */
3188 #ifdef AFS_FREELANCE
3189 if ( smb_localZero != old_localZero )
3190 cm_noteLocalMountPointChange();
3193 /* XXX GC dir search entries */
3197 void smb_WaitingLocksDaemon()
3199 smb_waitingLockRequest_t *wlRequest, *nwlRequest;
3200 smb_waitingLock_t *wl, *wlNext;
3203 smb_packet_t *inp, *outp;
3207 while (smbShutdownFlag == 0) {
3208 lock_ObtainWrite(&smb_globalLock);
3209 nwlRequest = smb_allWaitingLocks;
3210 if (nwlRequest == NULL) {
3211 osi_SleepW((LONG_PTR)&smb_allWaitingLocks, &smb_globalLock);
3216 osi_Log0(smb_logp, "smb_WaitingLocksDaemon starting wait lock check");
3223 lock_ObtainWrite(&smb_globalLock);
3225 osi_Log1(smb_logp, " Checking waiting lock request %p", nwlRequest);
3227 wlRequest = nwlRequest;
3228 nwlRequest = (smb_waitingLockRequest_t *) osi_QNext(&wlRequest->q);
3229 lock_ReleaseWrite(&smb_globalLock);
3233 for (wl = wlRequest->locks; wl; wl = (smb_waitingLock_t *) osi_QNext(&wl->q)) {
3234 if (wl->state == SMB_WAITINGLOCKSTATE_DONE)
3237 osi_assert(wl->state != SMB_WAITINGLOCKSTATE_ERROR);
3239 /* wl->state is either _DONE or _WAITING. _ERROR
3240 would no longer be on the queue. */
3241 code = cm_RetryLock( wl->lockp,
3242 !!(wlRequest->vcp->flags & SMB_VCFLAG_ALREADYDEAD) );
3245 wl->state = SMB_WAITINGLOCKSTATE_DONE;
3246 } else if (code != CM_ERROR_WOULDBLOCK) {
3247 wl->state = SMB_WAITINGLOCKSTATE_ERROR;
3252 if (code == CM_ERROR_WOULDBLOCK) {
3255 if (wlRequest->timeRemaining != 0xffffffff
3256 && (wlRequest->timeRemaining -= 1000) < 0)
3268 osi_Log1(smb_logp, "smb_WaitingLocksDaemon discarding lock req %p",
3271 scp = wlRequest->scp;
3275 lock_ObtainMutex(&scp->mx);
3277 for (wl = wlRequest->locks; wl; wl = wlNext) {
3278 wlNext = (smb_waitingLock_t *) osi_QNext(&wl->q);
3280 cm_Unlock(scp, wlRequest->lockType, wl->LOffset,
3281 wl->LLength, wl->key, NULL, &req);
3283 osi_QRemove((osi_queue_t **) &wlRequest->locks, &wl->q);
3288 lock_ReleaseMutex(&scp->mx);
3292 osi_Log1(smb_logp, "smb_WaitingLocksDaemon granting lock req %p",
3295 for (wl = wlRequest->locks; wl; wl = wlNext) {
3296 wlNext = (smb_waitingLock_t *) osi_QNext(&wl->q);
3297 osi_QRemove((osi_queue_t **) &wlRequest->locks, &wl->q);
3302 vcp = wlRequest->vcp;
3303 inp = wlRequest->inp;
3304 outp = wlRequest->outp;
3306 ncbp->ncb_length = inp->ncb_length;
3307 inp->spacep = cm_GetSpace();
3309 /* Remove waitingLock from list */
3310 lock_ObtainWrite(&smb_globalLock);
3311 osi_QRemove((osi_queue_t **)&smb_allWaitingLocks,
3313 lock_ReleaseWrite(&smb_globalLock);
3315 /* Resume packet processing */
3317 smb_SetSMBDataLength(outp, 0);
3318 outp->flags |= SMB_PACKETFLAG_SUSPENDED;
3319 outp->resumeCode = code;
3321 smb_DispatchPacket(vcp, inp, outp, ncbp, NULL);
3324 cm_FreeSpace(inp->spacep);
3325 smb_FreePacket(inp);
3326 smb_FreePacket(outp);
3328 cm_ReleaseSCache(wlRequest->scp);
3331 } while (nwlRequest && smbShutdownFlag == 0);
3336 long smb_ReceiveCoreGetDiskAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
3338 osi_Log0(smb_logp, "SMB receive get disk attributes");
3340 smb_SetSMBParm(outp, 0, 32000);
3341 smb_SetSMBParm(outp, 1, 64);
3342 smb_SetSMBParm(outp, 2, 1024);
3343 smb_SetSMBParm(outp, 3, 30000);
3344 smb_SetSMBParm(outp, 4, 0);
3345 smb_SetSMBDataLength(outp, 0);
3349 long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *rsp)
3353 unsigned short newTid;
3354 char shareName[256];
3362 osi_Log0(smb_logp, "SMB receive tree connect");
3364 /* parse input parameters */
3365 tp = smb_GetSMBData(inp, NULL);
3366 pathp = smb_ParseASCIIBlock(tp, &tp);
3367 if (smb_StoreAnsiFilenames)
3368 OemToChar(pathp,pathp);
3369 passwordp = smb_ParseASCIIBlock(tp, &tp);
3370 tp = strrchr(pathp, '\\');
3372 return CM_ERROR_BADSMB;
3373 strcpy(shareName, tp+1);
3375 userp = smb_GetUser(vcp, inp);
3377 lock_ObtainMutex(&vcp->mx);
3378 newTid = vcp->tidCounter++;
3379 lock_ReleaseMutex(&vcp->mx);
3381 tidp = smb_FindTID(vcp, newTid, SMB_FLAG_CREATE);
3382 uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
3383 shareFound = smb_FindShare(vcp, uidp, shareName, &sharePath);
3385 smb_ReleaseUID(uidp);
3387 smb_ReleaseTID(tidp);
3388 return CM_ERROR_BADSHARENAME;
3390 lock_ObtainMutex(&tidp->mx);
3391 tidp->userp = userp;
3392 tidp->pathname = sharePath;
3393 lock_ReleaseMutex(&tidp->mx);
3394 smb_ReleaseTID(tidp);
3396 smb_SetSMBParm(rsp, 0, SMB_PACKETSIZE);
3397 smb_SetSMBParm(rsp, 1, newTid);
3398 smb_SetSMBDataLength(rsp, 0);
3400 osi_Log1(smb_logp, "SMB tree connect created ID %d", newTid);
3404 unsigned char *smb_ParseDataBlock(unsigned char *inp, char **chainpp, int *lengthp)
3408 if (*inp++ != 0x1) return NULL;
3409 tlen = inp[0] + (inp[1]<<8);
3410 inp += 2; /* skip length field */
3413 *chainpp = inp + tlen;
3416 if (lengthp) *lengthp = tlen;
3421 /* set maskp to the mask part of the incoming path.
3422 * Mask is 11 bytes long (8.3 with the dot elided).
3423 * Returns true if succeeds with a valid name, otherwise it does
3424 * its best, but returns false.
3426 int smb_Get8Dot3MaskFromPath(unsigned char *maskp, unsigned char *pathp)
3434 /* starts off valid */
3437 /* mask starts out all blanks */
3438 memset(maskp, ' ', 11);
3440 /* find last backslash, or use whole thing if there is none */
3441 tp = strrchr(pathp, '\\');
3442 if (!tp) tp = pathp;
3443 else tp++; /* skip slash */
3447 /* names starting with a dot are illegal */
3448 if (*tp == '.') valid8Dot3 = 0;
3452 if (tc == 0) return valid8Dot3;
3453 if (tc == '.' || tc == '"') break;
3454 if (i < 8) *up++ = tc;
3455 else valid8Dot3 = 0;
3458 /* if we get here, tp point after the dot */
3459 up = maskp+8; /* ext goes here */
3466 if (tc == '.' || tc == '"')
3469 /* copy extension if not too long */
3479 int smb_Match8Dot3Mask(char *unixNamep, char *maskp)
3489 /* XXX redo this, calling smb_V3MatchMask with a converted mask */
3491 valid = smb_Get8Dot3MaskFromPath(umask, unixNamep);
3495 /* otherwise, we have a valid 8.3 name; see if we have a match,
3496 * treating '?' as a wildcard in maskp (but not in the file name).
3498 tp1 = umask; /* real name, in mask format */
3499 tp2 = maskp; /* mask, in mask format */
3500 for(i=0; i<11; i++) {
3501 tc1 = *tp1++; /* char from real name */
3502 tc2 = *tp2++; /* char from mask */
3503 tc1 = (char) cm_foldUpper[(unsigned char)tc1];
3504 tc2 = (char) cm_foldUpper[(unsigned char)tc2];
3507 if (tc2 == '?' && tc1 != ' ')
3514 /* we got a match */
3518 char *smb_FindMask(char *pathp)
3522 tp = strrchr(pathp, '\\'); /* find last slash */
3525 return tp+1; /* skip the slash */
3527 return pathp; /* no slash, return the entire path */
3530 long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
3532 unsigned char *pathp;
3534 unsigned char mask[11];
3535 unsigned char *statBlockp;
3536 unsigned char initStatBlock[21];
3539 osi_Log0(smb_logp, "SMB receive search volume");
3541 /* pull pathname and stat block out of request */
3542 tp = smb_GetSMBData(inp, NULL);
3543 pathp = smb_ParseASCIIBlock(tp, (char **) &tp);
3544 osi_assert(pathp != NULL);
3545 if (smb_StoreAnsiFilenames)
3546 OemToChar(pathp,pathp);
3547 statBlockp = smb_ParseVblBlock(tp, (char **) &tp, &statLen);
3548 osi_assert(statBlockp != NULL);
3550 statBlockp = initStatBlock;
3554 /* for returning to caller */
3555 smb_Get8Dot3MaskFromPath(mask, pathp);
3557 smb_SetSMBParm(outp, 0, 1); /* we're returning one entry */
3558 tp = smb_GetSMBData(outp, NULL);
3560 *tp++ = 43; /* bytes in a dir entry */
3561 *tp++ = 0; /* high byte in counter */
3563 /* now marshall the dir entry, starting with the search status */
3564 *tp++ = statBlockp[0]; /* Reserved */
3565 memcpy(tp, mask, 11); tp += 11; /* FileName */
3567 /* now pass back server use info, with 1st byte non-zero */
3569 memset(tp, 0, 4); tp += 4; /* reserved for server use */
3571 memcpy(tp, statBlockp+17, 4); tp += 4; /* reserved for consumer */
3573 *tp++ = 0x8; /* attribute: volume */
3583 /* 4 byte file size */
3589 /* finally, null-terminated 8.3 pathname, which we set to AFS */
3590 memset(tp, ' ', 13);
3593 /* set the length of the data part of the packet to 43 + 3, for the dir
3594 * entry plus the 5 and the length fields.
3596 smb_SetSMBDataLength(outp, 46);
3600 long smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
3601 cm_user_t *userp, cm_req_t *reqp)
3609 smb_dirListPatch_t *patchp;
3610 smb_dirListPatch_t *npatchp;
3612 for (patchp = *dirPatchespp; patchp; patchp =
3613 (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
3615 dptr = patchp->dptr;
3617 code = cm_GetSCache(&patchp->fid, &scp, userp, reqp);
3619 if( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
3620 *dptr++ = SMB_ATTR_HIDDEN;
3623 lock_ObtainMutex(&scp->mx);
3624 code = cm_SyncOp(scp, NULL, userp, reqp, 0,
3625 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3627 lock_ReleaseMutex(&scp->mx);
3628 cm_ReleaseSCache(scp);
3629 if (patchp->flags & SMB_DIRLISTPATCH_DOTFILE)
3630 *dptr++ = SMB_ATTR_HIDDEN;
3634 attr = smb_Attributes(scp);
3635 /* check hidden attribute (the flag is only ON when dot file hiding is on ) */
3636 if (patchp->flags & SMB_DIRLISTPATCH_DOTFILE)
3637 attr |= SMB_ATTR_HIDDEN;
3641 smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
3644 shortTemp = (unsigned short) (dosTime & 0xffff);
3645 *((u_short *)dptr) = shortTemp;
3648 /* and copy out date */
3649 shortTemp = (unsigned short) ((dosTime>>16) & 0xffff);
3650 *((u_short *)dptr) = shortTemp;
3653 /* copy out file length */
3654 *((u_long *)dptr) = scp->length.LowPart;
3656 lock_ReleaseMutex(&scp->mx);
3657 cm_ReleaseSCache(scp);
3660 /* now free the patches */
3661 for (patchp = *dirPatchespp; patchp; patchp = npatchp) {
3662 npatchp = (smb_dirListPatch_t *) osi_QNext(&patchp->q);
3666 /* and mark the list as empty */
3667 *dirPatchespp = NULL;
3672 long smb_ReceiveCoreSearchDir(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
3681 smb_dirListPatch_t *dirListPatchesp;
3682 smb_dirListPatch_t *curPatchp;
3686 osi_hyper_t dirLength;
3687 osi_hyper_t bufferOffset;
3688 osi_hyper_t curOffset;
3690 unsigned char *inCookiep;
3691 smb_dirSearch_t *dsp;
3695 unsigned long clientCookie;
3696 cm_pageHeader_t *pageHeaderp;
3697 cm_user_t *userp = NULL;
3704 long nextEntryCookie;
3705 int numDirChunks; /* # of 32 byte dir chunks in this entry */
3706 char resByte; /* reserved byte from the cookie */
3707 char *op; /* output data ptr */
3708 char *origOp; /* original value of op */
3709 cm_space_t *spacep; /* for pathname buffer */
3720 maxCount = smb_GetSMBParm(inp, 0);
3722 dirListPatchesp = NULL;
3724 caseFold = CM_FLAG_CASEFOLD;
3726 tp = smb_GetSMBData(inp, NULL);
3727 pathp = smb_ParseASCIIBlock(tp, &tp);
3728 if (smb_StoreAnsiFilenames)
3729 OemToChar(pathp,pathp);
3730 inCookiep = smb_ParseVblBlock(tp, &tp, &dataLength);
3732 /* bail out if request looks bad */
3733 if (!tp || !pathp) {
3734 return CM_ERROR_BADSMB;
3737 /* We can handle long names */
3738 if (vcp->flags & SMB_VCFLAG_USENT)
3739 ((smb_t *)outp)->flg2 |= SMB_FLAGS2_IS_LONG_NAME;
3741 /* make sure we got a whole search status */
3742 if (dataLength < 21) {