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>
25 #include <rx/rx_prototypes.h>
26 #include <WINNT\afsreg.h>
29 #include "lanahelper.h"
31 /* These characters are illegal in Windows filenames */
32 static char *illegalChars = "\\/:*?\"<>|";
34 int smbShutdownFlag = 0;
36 int smb_LogoffTokenTransfer;
37 time_t smb_LogoffTransferTimeout;
39 int smb_StoreAnsiFilenames = 0;
41 DWORD last_msg_time = 0;
45 unsigned int sessionGen = 0;
47 extern void afsi_log(char *pattern, ...);
48 extern HANDLE afsi_file;
50 osi_hyper_t hzero = {0, 0};
51 osi_hyper_t hones = {0xFFFFFFFF, -1};
54 osi_rwlock_t smb_globalLock;
55 osi_rwlock_t smb_rctLock;
56 osi_mutex_t smb_ListenerLock;
59 unsigned char smb_sharename[NCBNAMSZ+1] = {0};
62 long smb_maxObsConcurrentCalls=0;
63 long smb_concurrentCalls=0;
65 smb_dispatch_t smb_dispatchTable[SMB_NOPCODES];
67 smb_packet_t *smb_packetFreeListp;
68 smb_ncb_t *smb_ncbFreeListp;
70 int smb_NumServerThreads;
72 int numNCBs, numSessions, numVCs;
74 int smb_maxVCPerServer;
75 int smb_maxMpxRequests;
77 int smb_authType = SMB_AUTH_EXTENDED; /* type of SMB auth to use. One of SMB_AUTH_* */
79 ULONG smb_lsaSecPackage;
80 LSA_STRING smb_lsaLogonOrigin;
82 #define NCB_MAX MAXIMUM_WAIT_OBJECTS
83 EVENT_HANDLE NCBavails[NCB_MAX], NCBevents[NCB_MAX];
84 EVENT_HANDLE **NCBreturns;
85 EVENT_HANDLE **NCBShutdown;
86 EVENT_HANDLE *smb_ServerShutdown;
87 DWORD NCBsessions[NCB_MAX];
89 struct smb_packet *bufs[NCB_MAX];
91 #define SESSION_MAX MAXIMUM_WAIT_OBJECTS - 4
92 EVENT_HANDLE SessionEvents[SESSION_MAX];
93 unsigned short LSNs[SESSION_MAX];
94 int lanas[SESSION_MAX];
95 BOOL dead_sessions[SESSION_MAX];
99 osi_mutex_t smb_RawBufLock;
102 #define SMB_MASKFLAG_TILDE 1
103 #define SMB_MASKFLAG_CASEFOLD 2
105 #define RAWTIMEOUT INFINITE
108 typedef struct raw_write_cont {
117 /* dir search stuff */
118 long smb_dirSearchCounter = 1;
119 smb_dirSearch_t *smb_firstDirSearchp;
120 smb_dirSearch_t *smb_lastDirSearchp;
122 /* hide dot files? */
123 int smb_hideDotFiles;
125 /* global state about V3 protocols */
126 int smb_useV3; /* try to negotiate V3 */
128 static showErrors = 0;
129 /* MessageBox or something like it */
130 int (_stdcall *smb_MBfunc)(HWND, LPCTSTR, LPCTSTR, UINT) = NULL;
133 * Time in Unix format of midnight, 1/1/1970 local time.
134 * When added to dosUTime, gives Unix (AFS) time.
136 time_t smb_localZero = 0;
138 #define USE_NUMERIC_TIME_CONV 1
140 #ifndef USE_NUMERIC_TIME_CONV
141 /* Time difference for converting to kludge-GMT */
142 afs_uint32 smb_NowTZ;
143 #endif /* USE_NUMERIC_TIME_CONV */
145 char *smb_localNamep = NULL;
147 smb_vc_t *smb_allVCsp;
148 smb_vc_t *smb_deadVCsp;
150 smb_username_t *usernamesp = NULL;
152 smb_waitingLockRequest_t *smb_allWaitingLocks;
154 DWORD smb_TlsRequestSlot = -1;
157 void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
158 NCB *ncbp, raw_write_cont_t *rwcp);
159 void smb_NetbiosInit();
162 void smb_LogPacket(smb_packet_t *packet);
163 #endif /* LOG_PACKET */
165 char smb_ServerDomainName[MAX_COMPUTERNAME_LENGTH + 1] = ""; /* domain name */
166 int smb_ServerDomainNameLength = 0;
167 char smb_ServerOS[] = "Windows 5.0"; /* Faux OS String */
168 int smb_ServerOSLength = sizeof(smb_ServerOS);
169 char smb_ServerLanManager[] = "Windows 2000 LAN Manager"; /* Faux LAN Manager string */
170 int smb_ServerLanManagerLength = sizeof(smb_ServerLanManager);
172 /* Faux server GUID. This is never checked. */
173 GUID smb_ServerGUID = { 0x40015cb8, 0x058a, 0x44fc, { 0xae, 0x7e, 0xbb, 0x29, 0x52, 0xee, 0x7e, 0xff }};
175 void smb_ResetServerPriority()
177 void * p = TlsGetValue(smb_TlsRequestSlot);
180 TlsSetValue(smb_TlsRequestSlot, NULL);
181 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
185 void smb_SetRequestStartTime()
187 time_t * tp = TlsGetValue(smb_TlsRequestSlot);
189 tp = malloc(sizeof(time_t));
193 if (!TlsSetValue(smb_TlsRequestSlot, tp))
198 void smb_UpdateServerPriority()
200 time_t *tp = TlsGetValue(smb_TlsRequestSlot);
203 time_t now = osi_Time();
205 /* Give one priority boost for each 15 seconds */
206 SetThreadPriority(GetCurrentThread(), (now - *tp) / 15);
211 const char * ncb_error_string(int code)
215 case 0x01: s = "llegal buffer length"; break;
216 case 0x03: s = "illegal command"; break;
217 case 0x05: s = "command timed out"; break;
218 case 0x06: s = "message incomplete, issue another command"; break;
219 case 0x07: s = "illegal buffer address"; break;
220 case 0x08: s = "session number out of range"; break;
221 case 0x09: s = "no resource available"; break;
222 case 0x0a: s = "session closed"; break;
223 case 0x0b: s = "command cancelled"; break;
224 case 0x0d: s = "duplicate name"; break;
225 case 0x0e: s = "name table full"; break;
226 case 0x0f: s = "no deletions, name has active sessions"; break;
227 case 0x11: s = "local session table full"; break;
228 case 0x12: s = "remote session table full"; break;
229 case 0x13: s = "illegal name number"; break;
230 case 0x14: s = "no callname"; break;
231 case 0x15: s = "cannot put * in NCB_NAME"; break;
232 case 0x16: s = "name in use on remote adapter"; break;
233 case 0x17: s = "name deleted"; break;
234 case 0x18: s = "session ended abnormally"; break;
235 case 0x19: s = "name conflict detected"; break;
236 case 0x21: s = "interface busy, IRET before retrying"; break;
237 case 0x22: s = "too many commands outstanding, retry later";break;
238 case 0x23: s = "ncb_lana_num field invalid"; break;
239 case 0x24: s = "command completed while cancel occurring "; break;
240 case 0x26: s = "command not valid to cancel"; break;
241 case 0x30: s = "name defined by anther local process"; break;
242 case 0x34: s = "environment undefined. RESET required"; break;
243 case 0x35: s = "required OS resources exhausted"; break;
244 case 0x36: s = "max number of applications exceeded"; break;
245 case 0x37: s = "no saps available for netbios"; break;
246 case 0x38: s = "requested resources are not available"; break;
247 case 0x39: s = "invalid ncb address or length > segment"; break;
248 case 0x3B: s = "invalid NCB DDID"; break;
249 case 0x3C: s = "lock of user area failed"; break;
250 case 0x3f: s = "NETBIOS not loaded"; break;
251 case 0x40: s = "system error"; break;
252 default: s = "unknown error";
258 char * myCrt_Dispatch(int i)
263 return "(00)ReceiveCoreMakeDir";
265 return "(01)ReceiveCoreRemoveDir";
267 return "(02)ReceiveCoreOpen";
269 return "(03)ReceiveCoreCreate";
271 return "(04)ReceiveCoreClose";
273 return "(05)ReceiveCoreFlush";
275 return "(06)ReceiveCoreUnlink";
277 return "(07)ReceiveCoreRename";
279 return "(08)ReceiveCoreGetFileAttributes";
281 return "(09)ReceiveCoreSetFileAttributes";
283 return "(0a)ReceiveCoreRead";
285 return "(0b)ReceiveCoreWrite";
287 return "(0c)ReceiveCoreLockRecord";
289 return "(0d)ReceiveCoreUnlockRecord";
291 return "(0e)SendCoreBadOp";
293 return "(0f)ReceiveCoreCreate";
295 return "(10)ReceiveCoreCheckPath";
297 return "(11)SendCoreBadOp";
299 return "(12)ReceiveCoreSeek";
301 return "(1a)ReceiveCoreReadRaw";
303 return "(1d)ReceiveCoreWriteRawDummy";
305 return "(22)ReceiveV3SetAttributes";
307 return "(23)ReceiveV3GetAttributes";
309 return "(24)ReceiveV3LockingX";
311 return "(25)ReceiveV3Trans";
313 return "(26)ReceiveV3Trans[aux]";
315 return "(29)SendCoreBadOp";
317 return "(2b)ReceiveCoreEcho";
319 return "(2d)ReceiveV3OpenX";
321 return "(2e)ReceiveV3ReadX";
323 return "(2f)ReceiveV3WriteX";
325 return "(32)ReceiveV3Tran2A";
327 return "(33)ReceiveV3Tran2A[aux]";
329 return "(34)ReceiveV3FindClose";
331 return "(35)ReceiveV3FindNotifyClose";
333 return "(70)ReceiveCoreTreeConnect";
335 return "(71)ReceiveCoreTreeDisconnect";
337 return "(72)ReceiveNegotiate";
339 return "(73)ReceiveV3SessionSetupX";
341 return "(74)ReceiveV3UserLogoffX";
343 return "(75)ReceiveV3TreeConnectX";
345 return "(80)ReceiveCoreGetDiskAttributes";
347 return "(81)ReceiveCoreSearchDir";
351 return "(83)FindUnique";
353 return "(84)FindClose";
355 return "(A0)ReceiveNTTransact";
357 return "(A2)ReceiveNTCreateX";
359 return "(A4)ReceiveNTCancel";
361 return "(A5)ReceiveNTRename";
363 return "(C0)OpenPrintFile";
365 return "(C1)WritePrintFile";
367 return "(C2)ClosePrintFile";
369 return "(C3)GetPrintQueue";
371 return "(D8)ReadBulk";
373 return "(D9)WriteBulk";
375 return "(DA)WriteBulkData";
377 return "unknown SMB op";
381 char * myCrt_2Dispatch(int i)
386 return "unknown SMB op-2";
388 return "S(00)CreateFile_ReceiveTran2Open";
390 return "S(01)FindFirst_ReceiveTran2SearchDir";
392 return "S(02)FindNext_ReceiveTran2SearchDir"; /* FindNext */
394 return "S(03)QueryFileSystem_ReceiveTran2QFSInfo";
396 return "S(04)SetFileSystem_ReceiveTran2SetFSInfo";
398 return "S(05)QueryPathInfo_ReceiveTran2QPathInfo";
400 return "S(06)SetPathInfo_ReceiveTran2SetPathInfo";
402 return "S(07)QueryFileInfo_ReceiveTran2QFileInfo";
404 return "S(08)SetFileInfo_ReceiveTran2SetFileInfo";
406 return "S(09)_ReceiveTran2FSCTL";
408 return "S(0a)_ReceiveTran2IOCTL";
410 return "S(0b)_ReceiveTran2FindNotifyFirst";
412 return "S(0c)_ReceiveTran2FindNotifyNext";
414 return "S(0d)_ReceiveTran2CreateDirectory";
416 return "S(0e)_ReceiveTran2SessionSetup";
418 return "S(0f)_QueryFileSystemInformationFid";
420 return "S(10)_ReceiveTran2GetDfsReferral";
422 return "S(11)_ReceiveTran2ReportDfsInconsistency";
426 char * myCrt_RapDispatch(int i)
431 return "unknown RAP OP";
433 return "RAP(0)NetShareEnum";
435 return "RAP(1)NetShareGetInfo";
437 return "RAP(13)NetServerGetInfo";
439 return "RAP(63)NetWkStaGetInfo";
443 /* scache must be locked */
444 unsigned int smb_Attributes(cm_scache_t *scp)
448 if ( scp->fileType == CM_SCACHETYPE_DIRECTORY ||
449 scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
450 scp->fileType == CM_SCACHETYPE_INVALID)
452 attrs = SMB_ATTR_DIRECTORY;
453 #ifdef SPECIAL_FOLDERS
454 attrs |= SMB_ATTR_SYSTEM; /* FILE_ATTRIBUTE_SYSTEM */
455 #endif /* SPECIAL_FOLDERS */
456 } else if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
457 attrs = SMB_ATTR_DIRECTORY | SMB_ATTR_SPARSE_FILE;
462 * We used to mark a file RO if it was in an RO volume, but that
463 * turns out to be impolitic in NT. See defect 10007.
466 if ((scp->unixModeBits & 0222) == 0 || (scp->flags & CM_SCACHEFLAG_RO))
467 attrs |= SMB_ATTR_READONLY; /* turn on read-only flag */
469 if ((scp->unixModeBits & 0222) == 0)
470 attrs |= SMB_ATTR_READONLY; /* turn on read-only flag */
476 /* Check if the named file/dir is a dotfile/dotdir */
477 /* String pointed to by lastComp can have leading slashes, but otherwise should have
478 no other patch components */
479 unsigned int smb_IsDotFile(char *lastComp) {
482 /* skip over slashes */
483 for(s=lastComp;*s && (*s == '\\' || *s == '/'); s++);
488 /* nulls, curdir and parent dir doesn't count */
494 if(*(s+1) == '.' && !*(s + 2))
501 static int ExtractBits(WORD bits, short start, short len)
508 num = bits << (16 - end);
509 num = num >> ((16 - end) + start);
514 void ShowUnixTime(char *FuncName, time_t unixTime)
519 smb_LargeSearchTimeFromUnixTime(&ft, unixTime);
521 if (!FileTimeToDosDateTime(&ft, &wDate, &wTime))
522 osi_Log1(smb_logp, "Failed to convert filetime to dos datetime: %d", GetLastError());
524 int day, month, year, sec, min, hour;
527 day = ExtractBits(wDate, 0, 5);
528 month = ExtractBits(wDate, 5, 4);
529 year = ExtractBits(wDate, 9, 7) + 1980;
531 sec = ExtractBits(wTime, 0, 5);
532 min = ExtractBits(wTime, 5, 6);
533 hour = ExtractBits(wTime, 11, 5);
535 sprintf(msg, "%s = %02d-%02d-%04d %02d:%02d:%02d", FuncName, month, day, year, hour, min, sec);
536 osi_Log1(smb_logp, "%s", osi_LogSaveString(smb_logp, msg));
540 /* Determine if we are observing daylight savings time */
541 void GetTimeZoneInfo(BOOL *pDST, LONG *pDstBias, LONG *pBias)
543 TIME_ZONE_INFORMATION timeZoneInformation;
544 SYSTEMTIME utc, local, localDST;
546 /* Get the time zone info. NT uses this to calc if we are in DST. */
547 GetTimeZoneInformation(&timeZoneInformation);
549 /* Return the daylight bias */
550 *pDstBias = timeZoneInformation.DaylightBias;
552 /* Return the bias */
553 *pBias = timeZoneInformation.Bias;
555 /* Now determine if DST is being observed */
557 /* Get the UTC (GMT) time */
560 /* Convert UTC time to local time using the time zone info. If we are
561 observing DST, the calculated local time will include this.
563 SystemTimeToTzSpecificLocalTime(&timeZoneInformation, &utc, &localDST);
565 /* Set the daylight bias to 0. The daylight bias is the amount of change
566 * in time that we use for daylight savings time. By setting this to 0
567 * we cause there to be no change in time during daylight savings time.
569 timeZoneInformation.DaylightBias = 0;
571 /* Convert the utc time to local time again, but this time without any
572 adjustment for daylight savings time.
574 SystemTimeToTzSpecificLocalTime(&timeZoneInformation, &utc, &local);
576 /* If the two times are different, then it means that the localDST that
577 we calculated includes the daylight bias, and therefore we are
578 observing daylight savings time.
580 *pDST = localDST.wHour != local.wHour;
584 void CompensateForSmbClientLastWriteTimeBugs(afs_uint32 *pLastWriteTime)
586 BOOL dst; /* Will be TRUE if observing DST */
587 LONG dstBias; /* Offset from local time if observing DST */
588 LONG bias; /* Offset from GMT for local time */
591 * This function will adjust the last write time to compensate
592 * for two bugs in the smb client:
594 * 1) During Daylight Savings Time, the LastWriteTime is ahead
595 * in time by the DaylightBias (ignoring the sign - the
596 * DaylightBias is always stored as a negative number). If
597 * the DaylightBias is -60, then the LastWriteTime will be
598 * ahead by 60 minutes.
600 * 2) If the local time zone is a positive offset from GMT, then
601 * the LastWriteTime will be the correct local time plus the
602 * Bias (ignoring the sign - a positive offset from GMT is
603 * always stored as a negative Bias). If the Bias is -120,
604 * then the LastWriteTime will be ahead by 120 minutes.
606 * These bugs can occur at the same time.
609 GetTimeZoneInfo(&dst, &dstBias, &bias);
611 /* First adjust for DST */
613 *pLastWriteTime -= (-dstBias * 60); /* Convert dstBias to seconds */
615 /* Now adjust for a positive offset from GMT (a negative bias). */
617 *pLastWriteTime -= (-bias * 60); /* Convert bias to seconds */
620 #ifndef USE_NUMERIC_TIME_CONV
622 * Calculate the difference (in seconds) between local time and GMT.
623 * This enables us to convert file times to kludge-GMT.
629 struct tm gmt_tm, local_tm;
630 int days, hours, minutes, seconds;
633 gmt_tm = *(gmtime(&t));
634 local_tm = *(localtime(&t));
636 days = local_tm.tm_yday - gmt_tm.tm_yday;
637 hours = 24 * days + local_tm.tm_hour - gmt_tm.tm_hour;
638 minutes = 60 * hours + local_tm.tm_min - gmt_tm.tm_min;
639 seconds = 60 * minutes + local_tm.tm_sec - gmt_tm.tm_sec;
643 #endif /* USE_NUMERIC_TIME_CONV */
645 #ifdef USE_NUMERIC_TIME_CONV
646 void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
648 // Note that LONGLONG is a 64-bit value
651 ll = Int32x32To64(unixTime, 10000000) + 116444736000000000;
652 largeTimep->dwLowDateTime = (DWORD)(ll & 0xFFFFFFFF);
653 largeTimep->dwHighDateTime = (DWORD)(ll >> 32);
656 void smb_LargeSearchTimeFromUnixTime(FILETIME *largeTimep, time_t unixTime)
661 time_t ersatz_unixTime;
664 * Must use kludge-GMT instead of real GMT.
665 * kludge-GMT is computed by adding time zone difference to localtime.
668 * ltp = gmtime(&unixTime);
670 ersatz_unixTime = unixTime - smb_NowTZ;
671 ltp = localtime(&ersatz_unixTime);
673 /* if we fail, make up something */
676 localJunk.tm_year = 89 - 20;
677 localJunk.tm_mon = 4;
678 localJunk.tm_mday = 12;
679 localJunk.tm_hour = 0;
680 localJunk.tm_min = 0;
681 localJunk.tm_sec = 0;
684 stm.wYear = ltp->tm_year + 1900;
685 stm.wMonth = ltp->tm_mon + 1;
686 stm.wDayOfWeek = ltp->tm_wday;
687 stm.wDay = ltp->tm_mday;
688 stm.wHour = ltp->tm_hour;
689 stm.wMinute = ltp->tm_min;
690 stm.wSecond = ltp->tm_sec;
691 stm.wMilliseconds = 0;
693 SystemTimeToFileTime(&stm, largeTimep);
695 #endif /* USE_NUMERIC_TIME_CONV */
697 #ifdef USE_NUMERIC_TIME_CONV
698 void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
700 // Note that LONGLONG is a 64-bit value
703 ll = largeTimep->dwHighDateTime;
705 ll += largeTimep->dwLowDateTime;
707 ll -= 116444736000000000;
710 *unixTimep = (DWORD)ll;
712 #else /* USE_NUMERIC_TIME_CONV */
713 void smb_UnixTimeFromLargeSearchTime(time_t *unixTimep, FILETIME *largeTimep)
719 FileTimeToSystemTime(largeTimep, &stm);
721 lt.tm_year = stm.wYear - 1900;
722 lt.tm_mon = stm.wMonth - 1;
723 lt.tm_wday = stm.wDayOfWeek;
724 lt.tm_mday = stm.wDay;
725 lt.tm_hour = stm.wHour;
726 lt.tm_min = stm.wMinute;
727 lt.tm_sec = stm.wSecond;
730 save_timezone = _timezone;
731 _timezone += smb_NowTZ;
732 *unixTimep = mktime(<);
733 _timezone = save_timezone;
735 #endif /* USE_NUMERIC_TIME_CONV */
737 void smb_SearchTimeFromUnixTime(afs_uint32 *searchTimep, time_t unixTime)
747 /* if we fail, make up something */
750 localJunk.tm_year = 89 - 20;
751 localJunk.tm_mon = 4;
752 localJunk.tm_mday = 12;
753 localJunk.tm_hour = 0;
754 localJunk.tm_min = 0;
755 localJunk.tm_sec = 0;
758 dosDate = ((ltp->tm_year-80)<<9) | ((ltp->tm_mon+1) << 5) | (ltp->tm_mday);
759 dosTime = (ltp->tm_hour<<11) | (ltp->tm_min << 5) | (ltp->tm_sec / 2);
760 *searchTimep = (dosDate<<16) | dosTime;
763 void smb_UnixTimeFromSearchTime(time_t *unixTimep, afs_uint32 searchTime)
765 unsigned short dosDate;
766 unsigned short dosTime;
769 dosDate = (unsigned short) (searchTime & 0xffff);
770 dosTime = (unsigned short) ((searchTime >> 16) & 0xffff);
772 localTm.tm_year = 80 + ((dosDate>>9) & 0x3f);
773 localTm.tm_mon = ((dosDate >> 5) & 0xf) - 1; /* January is 0 in localTm */
774 localTm.tm_mday = (dosDate) & 0x1f;
775 localTm.tm_hour = (dosTime>>11) & 0x1f;
776 localTm.tm_min = (dosTime >> 5) & 0x3f;
777 localTm.tm_sec = (dosTime & 0x1f) * 2;
778 localTm.tm_isdst = -1; /* compute whether DST in effect */
780 *unixTimep = mktime(&localTm);
783 void smb_DosUTimeFromUnixTime(afs_uint32 *dosUTimep, time_t unixTime)
785 time_t diff_t = unixTime - smb_localZero;
786 #if defined(DEBUG) && !defined(_USE_32BIT_TIME_T)
787 osi_assert(diff_t < _UI32_MAX);
789 *dosUTimep = (afs_uint32)diff_t;
792 void smb_UnixTimeFromDosUTime(time_t *unixTimep, afs_uint32 dosTime)
794 *unixTimep = dosTime + smb_localZero;
797 smb_vc_t *smb_FindVC(unsigned short lsn, int flags, int lana)
801 lock_ObtainWrite(&smb_globalLock); /* for numVCs */
802 lock_ObtainWrite(&smb_rctLock);
803 for (vcp = smb_allVCsp; vcp; vcp=vcp->nextp) {
804 if (vcp->magic != SMB_VC_MAGIC)
805 osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
808 if (lsn == vcp->lsn && lana == vcp->lana &&
809 !(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
810 smb_HoldVCNoLock(vcp);
814 if (!vcp && (flags & SMB_FLAG_CREATE)) {
815 vcp = malloc(sizeof(*vcp));
816 memset(vcp, 0, sizeof(*vcp));
817 vcp->vcID = ++numVCs;
818 vcp->magic = SMB_VC_MAGIC;
819 vcp->refCount = 2; /* smb_allVCsp and caller */
822 vcp->uidCounter = 1; /* UID 0 is reserved for blank user */
823 vcp->nextp = smb_allVCsp;
825 lock_InitializeMutex(&vcp->mx, "vc_t mutex");
830 if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
831 /* We must obtain a challenge for extended auth
832 * in case the client negotiates smb v3
834 NTSTATUS nts = STATUS_UNSUCCESSFUL, ntsEx = STATUS_UNSUCCESSFUL;
835 MSV1_0_LM20_CHALLENGE_REQUEST lsaReq;
836 PMSV1_0_LM20_CHALLENGE_RESPONSE lsaResp;
837 ULONG lsaRespSize = 0;
839 lsaReq.MessageType = MsV1_0Lm20ChallengeRequest;
841 nts = LsaCallAuthenticationPackage( smb_lsaHandle,
848 if (nts != STATUS_SUCCESS)
849 osi_Log4(smb_logp,"MsV1_0Lm20ChallengeRequest failure: nts 0x%x ntsEx 0x%x respSize is %u needs %u",
850 nts, ntsEx, sizeof(lsaReq), lsaRespSize);
851 osi_assert(nts == STATUS_SUCCESS); /* this had better work! */
853 memcpy(vcp->encKey, lsaResp->ChallengeToClient, MSV1_0_CHALLENGE_LENGTH);
854 LsaFreeReturnBuffer(lsaResp);
857 memset(vcp->encKey, 0, MSV1_0_CHALLENGE_LENGTH);
859 if (numVCs >= CM_SESSION_RESERVED) {
861 osi_Log0(smb_logp, "WARNING: numVCs wrapping around");
864 lock_ReleaseWrite(&smb_rctLock);
865 lock_ReleaseWrite(&smb_globalLock);
869 int smb_IsStarMask(char *maskp)
874 for(i=0; i<11; i++) {
876 if (tc == '?' || tc == '*' || tc == '>')
882 void smb_ReleaseVCInternal(smb_vc_t *vcp)
889 if (vcp->refCount == 0) {
890 if (vcp->flags & SMB_VCFLAG_ALREADYDEAD) {
891 /* remove VCP from smb_deadVCsp */
892 for (vcpp = &smb_deadVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
898 lock_FinalizeMutex(&vcp->mx);
899 memset(vcp,0,sizeof(smb_vc_t));
902 for (avcp = smb_allVCsp; avcp; avcp = avcp->nextp) {
906 osi_Log3(smb_logp,"VCP not dead and %sin smb_allVCsp vcp %x ref %d",
907 avcp?"not ":"",vcp, vcp->refCount);
909 GenerateMiniDump(NULL);
911 /* This is a wrong. However, I suspect that there is an undercount
912 * and I don't want to release 1.4.1 in a state that will allow
913 * smb_vc_t objects to be deallocated while still in the
914 * smb_allVCsp list. The list is supposed to keep a reference
915 * to the smb_vc_t. Put it back.
922 void smb_ReleaseVCNoLock(smb_vc_t *vcp)
924 osi_Log2(smb_logp,"smb_ReleaseVCNoLock vcp %x ref %d",vcp, vcp->refCount);
925 smb_ReleaseVCInternal(vcp);
928 void smb_ReleaseVC(smb_vc_t *vcp)
930 lock_ObtainWrite(&smb_rctLock);
931 osi_Log2(smb_logp,"smb_ReleaseVC vcp %x ref %d",vcp, vcp->refCount);
932 smb_ReleaseVCInternal(vcp);
933 lock_ReleaseWrite(&smb_rctLock);
936 void smb_HoldVCNoLock(smb_vc_t *vcp)
939 osi_Log2(smb_logp,"smb_HoldVCNoLock vcp %x ref %d",vcp, vcp->refCount);
942 void smb_HoldVC(smb_vc_t *vcp)
944 lock_ObtainWrite(&smb_rctLock);
946 osi_Log2(smb_logp,"smb_HoldVC vcp %x ref %d",vcp, vcp->refCount);
947 lock_ReleaseWrite(&smb_rctLock);
950 void smb_CleanupDeadVC(smb_vc_t *vcp)
958 smb_user_t *uidpIter;
959 smb_user_t *uidpNext;
963 lock_ObtainMutex(&vcp->mx);
964 if (vcp->flags & SMB_VCFLAG_CLEAN_IN_PROGRESS) {
965 lock_ReleaseMutex(&vcp->mx);
966 osi_Log1(smb_logp, "Clean of dead vcp 0x%x in progress", vcp);
969 vcp->flags |= SMB_VCFLAG_CLEAN_IN_PROGRESS;
970 lock_ReleaseMutex(&vcp->mx);
971 osi_Log1(smb_logp, "Cleaning up dead vcp 0x%x", vcp);
973 lock_ObtainWrite(&smb_rctLock);
974 /* remove VCP from smb_allVCsp */
975 for (vcpp = &smb_allVCsp; *vcpp; vcpp = &((*vcpp)->nextp)) {
976 if ((*vcpp)->magic != SMB_VC_MAGIC)
977 osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
981 vcp->nextp = smb_deadVCsp;
983 /* Hold onto the reference until we are done with this function */
988 for (fidpIter = vcp->fidsp; fidpIter; fidpIter = fidpNext) {
989 fidpNext = (smb_fid_t *) osi_QNext(&fidpIter->q);
991 if (fidpIter->delete)
995 osi_Log2(smb_logp, " Cleanup FID %d (fidp=0x%x)", fid, fidpIter);
997 smb_HoldFIDNoLock(fidpIter);
998 lock_ReleaseWrite(&smb_rctLock);
1000 smb_CloseFID(vcp, fidpIter, NULL, 0);
1001 smb_ReleaseFID(fidpIter);
1003 lock_ObtainWrite(&smb_rctLock);
1004 fidpNext = vcp->fidsp;
1007 for (tidpIter = vcp->tidsp; tidpIter; tidpIter = tidpNext) {
1008 tidpNext = tidpIter->nextp;
1009 if (tidpIter->delete)
1011 tidpIter->delete = 1;
1013 tid = tidpIter->tid;
1014 osi_Log2(smb_logp, " Cleanup TID %d (tidp=0x%x)", tid, tidpIter);
1016 smb_HoldTIDNoLock(tidpIter);
1017 lock_ReleaseWrite(&smb_rctLock);
1019 smb_ReleaseTID(tidpIter);
1021 lock_ObtainWrite(&smb_rctLock);
1022 tidpNext = vcp->tidsp;
1025 for (uidpIter = vcp->usersp; uidpIter; uidpIter = uidpNext) {
1026 uidpNext = uidpIter->nextp;
1027 if (uidpIter->delete)
1029 uidpIter->delete = 1;
1031 /* do not add an additional reference count for the smb_user_t
1032 * as the smb_vc_t already is holding a reference */
1033 lock_ReleaseWrite(&smb_rctLock);
1035 smb_ReleaseUID(uidpIter);
1037 lock_ObtainWrite(&smb_rctLock);
1038 uidpNext = vcp->usersp;
1041 /* The vcp is now on the deadVCsp list. We intentionally drop the
1042 * reference so that the refcount can reach 0 and we can delete it */
1043 smb_ReleaseVCNoLock(vcp);
1045 lock_ReleaseWrite(&smb_rctLock);
1046 osi_Log1(smb_logp, "Finished cleaning up dead vcp 0x%x", vcp);
1049 smb_tid_t *smb_FindTID(smb_vc_t *vcp, unsigned short tid, int flags)
1053 lock_ObtainWrite(&smb_rctLock);
1055 for (tidp = vcp->tidsp; tidp; tidp = tidp->nextp) {
1056 if (tidp->refCount == 0 && tidp->delete) {
1058 lock_ReleaseWrite(&smb_rctLock);
1059 smb_ReleaseTID(tidp);
1060 lock_ObtainWrite(&smb_rctLock);
1064 if (tid == tidp->tid) {
1069 if (!tidp && (flags & SMB_FLAG_CREATE)) {
1070 tidp = malloc(sizeof(*tidp));
1071 memset(tidp, 0, sizeof(*tidp));
1072 tidp->nextp = vcp->tidsp;
1075 smb_HoldVCNoLock(vcp);
1077 lock_InitializeMutex(&tidp->mx, "tid_t mutex");
1080 lock_ReleaseWrite(&smb_rctLock);
1084 void smb_HoldTIDNoLock(smb_tid_t *tidp)
1089 void smb_ReleaseTID(smb_tid_t *tidp)
1096 lock_ObtainWrite(&smb_rctLock);
1097 osi_assert(tidp->refCount-- > 0);
1098 if (tidp->refCount == 0 && (tidp->delete)) {
1099 ltpp = &tidp->vcp->tidsp;
1100 for(tp = *ltpp; tp; ltpp = &tp->nextp, tp = *ltpp) {
1104 osi_assert(tp != NULL);
1106 lock_FinalizeMutex(&tidp->mx);
1107 userp = tidp->userp; /* remember to drop ref later */
1109 smb_ReleaseVCNoLock(tidp->vcp);
1112 lock_ReleaseWrite(&smb_rctLock);
1114 cm_ReleaseUser(userp);
1117 smb_user_t *smb_FindUID(smb_vc_t *vcp, unsigned short uid, int flags)
1119 smb_user_t *uidp = NULL;
1121 lock_ObtainWrite(&smb_rctLock);
1122 for(uidp = vcp->usersp; uidp; uidp = uidp->nextp) {
1123 if (uid == uidp->userID) {
1125 osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] found-uid[%d] name[%s]",
1127 osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name : ""));
1131 if (!uidp && (flags & SMB_FLAG_CREATE)) {
1132 uidp = malloc(sizeof(*uidp));
1133 memset(uidp, 0, sizeof(*uidp));
1134 uidp->nextp = vcp->usersp;
1135 uidp->refCount = 2; /* one for the vcp and one for the caller */
1137 smb_HoldVCNoLock(vcp);
1139 lock_InitializeMutex(&uidp->mx, "user_t mutex");
1141 osi_Log3(smb_logp, "smb_FindUID vcp[0x%p] new-uid[%d] name[%s]",
1143 osi_LogSaveString(smb_logp,uidp->unp ? uidp->unp->name : ""));
1145 lock_ReleaseWrite(&smb_rctLock);
1149 smb_username_t *smb_FindUserByName(char *usern, char *machine, afs_uint32 flags)
1151 smb_username_t *unp= NULL;
1153 lock_ObtainWrite(&smb_rctLock);
1154 for(unp = usernamesp; unp; unp = unp->nextp) {
1155 if (stricmp(unp->name, usern) == 0 &&
1156 stricmp(unp->machine, machine) == 0) {
1161 if (!unp && (flags & SMB_FLAG_CREATE)) {
1162 unp = malloc(sizeof(*unp));
1163 memset(unp, 0, sizeof(*unp));
1165 unp->nextp = usernamesp;
1166 unp->name = strdup(usern);
1167 unp->machine = strdup(machine);
1169 lock_InitializeMutex(&unp->mx, "username_t mutex");
1170 if (flags & SMB_FLAG_AFSLOGON)
1171 unp->flags = SMB_USERNAMEFLAG_AFSLOGON;
1174 lock_ReleaseWrite(&smb_rctLock);
1178 smb_user_t *smb_FindUserByNameThisSession(smb_vc_t *vcp, char *usern)
1180 smb_user_t *uidp= NULL;
1182 lock_ObtainWrite(&smb_rctLock);
1183 for(uidp = vcp->usersp; uidp; uidp = uidp->nextp) {
1186 if (stricmp(uidp->unp->name, usern) == 0) {
1188 osi_Log3(smb_logp,"smb_FindUserByNameThisSession vcp[0x%p] uid[%d] match-name[%s]",
1189 vcp,uidp->userID,osi_LogSaveString(smb_logp,usern));
1194 lock_ReleaseWrite(&smb_rctLock);
1198 void smb_ReleaseUsername(smb_username_t *unp)
1201 smb_username_t **lupp;
1202 cm_user_t *userp = NULL;
1203 time_t now = osi_Time();
1205 lock_ObtainWrite(&smb_rctLock);
1206 osi_assert(unp->refCount-- > 0);
1207 if (unp->refCount == 0 && !(unp->flags & SMB_USERNAMEFLAG_AFSLOGON) &&
1208 (unp->flags & SMB_USERNAMEFLAG_LOGOFF)) {
1210 for(up = *lupp; up; lupp = &up->nextp, up = *lupp) {
1214 osi_assert(up != NULL);
1216 up->nextp = NULL; /* do not remove this */
1217 lock_FinalizeMutex(&unp->mx);
1223 lock_ReleaseWrite(&smb_rctLock);
1226 cm_ReleaseUser(userp);
1230 void smb_HoldUIDNoLock(smb_user_t *uidp)
1235 void smb_ReleaseUID(smb_user_t *uidp)
1239 smb_username_t *unp = NULL;
1241 lock_ObtainWrite(&smb_rctLock);
1242 osi_assert(uidp->refCount-- > 0);
1243 if (uidp->refCount == 0) {
1244 lupp = &uidp->vcp->usersp;
1245 for(up = *lupp; up; lupp = &up->nextp, up = *lupp) {
1249 osi_assert(up != NULL);
1251 lock_FinalizeMutex(&uidp->mx);
1253 smb_ReleaseVCNoLock(uidp->vcp);
1257 lock_ReleaseWrite(&smb_rctLock);
1261 cm_ReleaseUserVCRef(unp->userp);
1262 smb_ReleaseUsername(unp);
1266 cm_user_t *smb_GetUserFromUID(smb_user_t *uidp)
1268 cm_user_t *up = NULL;
1273 lock_ObtainMutex(&uidp->mx);
1275 up = uidp->unp->userp;
1278 lock_ReleaseMutex(&uidp->mx);
1284 /* retrieve a held reference to a user structure corresponding to an incoming
1286 * corresponding release function is cm_ReleaseUser.
1288 cm_user_t *smb_GetUserFromVCP(smb_vc_t *vcp, smb_packet_t *inp)
1291 cm_user_t *up = NULL;
1294 smbp = (smb_t *) inp;
1295 uidp = smb_FindUID(vcp, smbp->uid, 0);
1299 up = smb_GetUserFromUID(uidp);
1301 smb_ReleaseUID(uidp);
1306 * Return a pointer to a pathname extracted from a TID structure. The
1307 * TID structure is not held; assume it won't go away.
1309 long smb_LookupTIDPath(smb_vc_t *vcp, unsigned short tid, char ** treepath)
1314 tidp = smb_FindTID(vcp, tid, 0);
1318 if (tidp->flags & SMB_TIDFLAG_IPC) {
1319 code = CM_ERROR_TIDIPC;
1320 /* tidp->pathname would be NULL, but that's fine */
1322 *treepath = tidp->pathname;
1323 smb_ReleaseTID(tidp);
1328 /* check to see if we have a chained fid, that is, a fid that comes from an
1329 * OpenAndX message that ran earlier in this packet. In this case, the fid
1330 * field in a read, for example, request, isn't set, since the value is
1331 * supposed to be inherited from the openAndX call.
1333 int smb_ChainFID(int fid, smb_packet_t *inp)
1335 if (inp->fid == 0 || inp->inCount == 0)
1341 /* are we a priv'd user? What does this mean on NT? */
1342 int smb_SUser(cm_user_t *userp)
1347 /* find a file ID. If we pass in 0 we select an unused File ID.
1348 * If the SMB_FLAG_CREATE flag is set, we allocate a new
1349 * smb_fid_t data structure if desired File ID cannot be found.
1351 smb_fid_t *smb_FindFID(smb_vc_t *vcp, unsigned short fid, int flags)
1356 if (fid == 0 && !(flags & SMB_FLAG_CREATE))
1359 lock_ObtainWrite(&smb_rctLock);
1360 /* figure out if we need to allocate a new file ID */
1363 fid = vcp->fidCounter;
1367 for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
1368 if (fidp->refCount == 0 && fidp->delete) {
1370 lock_ReleaseWrite(&smb_rctLock);
1371 smb_ReleaseFID(fidp);
1372 lock_ObtainWrite(&smb_rctLock);
1375 if (fid == fidp->fid) {
1378 if (fid == 0xFFFF) {
1380 "New FID number wraps on vcp 0x%x", vcp);
1390 if (!fidp && (flags & SMB_FLAG_CREATE)) {
1391 char eventName[MAX_PATH];
1393 sprintf(eventName,"fid_t event vcp=%d fid=%d", vcp->vcID, fid);
1394 event = thrd_CreateEvent(NULL, FALSE, TRUE, eventName);
1395 if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
1396 osi_Log1(smb_logp, "Event Object Already Exists: %s", osi_LogSaveString(smb_logp, eventName));
1397 thrd_CloseHandle(event);
1399 if (fid == 0xFFFF) {
1400 osi_Log1(smb_logp, "New FID wraps around for vcp 0x%x", vcp);
1406 fidp = malloc(sizeof(*fidp));
1407 memset(fidp, 0, sizeof(*fidp));
1408 osi_QAdd((osi_queue_t **)&vcp->fidsp, &fidp->q);
1411 smb_HoldVCNoLock(vcp);
1412 lock_InitializeMutex(&fidp->mx, "fid_t mutex");
1414 fidp->curr_chunk = fidp->prev_chunk = -2;
1415 fidp->raw_write_event = event;
1417 vcp->fidCounter = fid+1;
1418 if (vcp->fidCounter == 0xFFFF) {
1419 osi_Log1(smb_logp, "fidCounter wrapped around for vcp 0x%x",
1421 vcp->fidCounter = 1;
1426 lock_ReleaseWrite(&smb_rctLock);
1430 smb_fid_t *smb_FindFIDByScache(smb_vc_t *vcp, cm_scache_t * scp)
1432 smb_fid_t *fidp = NULL;
1438 lock_ObtainWrite(&smb_rctLock);
1439 for(fidp = vcp->fidsp; fidp; fidp = (smb_fid_t *) osi_QNext(&fidp->q)) {
1440 if (scp == fidp->scp) {
1445 lock_ReleaseWrite(&smb_rctLock);
1449 void smb_HoldFIDNoLock(smb_fid_t *fidp)
1454 void smb_ReleaseFID(smb_fid_t *fidp)
1456 cm_scache_t *scp = NULL;
1457 cm_user_t *userp = NULL;
1458 smb_vc_t *vcp = NULL;
1459 smb_ioctl_t *ioctlp;
1461 lock_ObtainMutex(&fidp->mx);
1462 lock_ObtainWrite(&smb_rctLock);
1463 osi_assert(fidp->refCount-- > 0);
1464 if (fidp->refCount == 0 && (fidp->delete)) {
1467 scp = fidp->scp; /* release after lock is released */
1469 lock_ObtainMutex(&scp->mx);
1470 scp->flags &= ~CM_SCACHEFLAG_SMB_FID;
1471 lock_ReleaseMutex(&scp->mx);
1472 osi_Log2(afsd_logp,"smb_ReleaseFID fidp 0x%p scp 0x%p", fidp, scp);
1475 userp = fidp->userp;
1479 osi_QRemove((osi_queue_t **) &vcp->fidsp, &fidp->q);
1480 thrd_CloseHandle(fidp->raw_write_event);
1482 /* and see if there is ioctl stuff to free */
1483 ioctlp = fidp->ioctlp;
1486 cm_FreeSpace(ioctlp->prefix);
1487 if (ioctlp->inAllocp)
1488 free(ioctlp->inAllocp);
1489 if (ioctlp->outAllocp)
1490 free(ioctlp->outAllocp);
1493 lock_ReleaseMutex(&fidp->mx);
1494 lock_FinalizeMutex(&fidp->mx);
1498 smb_ReleaseVCNoLock(vcp);
1500 lock_ReleaseMutex(&fidp->mx);
1502 lock_ReleaseWrite(&smb_rctLock);
1504 /* now release the scache structure */
1506 cm_ReleaseSCache(scp);
1509 cm_ReleaseUser(userp);
1513 * Case-insensitive search for one string in another;
1514 * used to find variable names in submount pathnames.
1516 static char *smb_stristr(char *str1, char *str2)
1520 for (cursor = str1; *cursor; cursor++)
1521 if (stricmp(cursor, str2) == 0)
1528 * Substitute a variable value for its name in a submount pathname. Variable
1529 * name has been identified by smb_stristr() and is in substr. Variable name
1530 * length (plus one) is in substr_size. Variable value is in newstr.
1532 static void smb_subst(char *str1, char *substr, unsigned int substr_size,
1537 strcpy(temp, substr + substr_size - 1);
1538 strcpy(substr, newstr);
1542 char VNUserName[] = "%USERNAME%";
1543 char VNLCUserName[] = "%LCUSERNAME%";
1544 char VNComputerName[] = "%COMPUTERNAME%";
1545 char VNLCComputerName[] = "%LCCOMPUTERNAME%";
1548 typedef struct smb_findShare_rock {
1552 } smb_findShare_rock_t;
1554 #define SMB_FINDSHARE_EXACT_MATCH 1
1555 #define SMB_FINDSHARE_PARTIAL_MATCH 2
1557 long smb_FindShareProc(cm_scache_t *scp, cm_dirEntry_t *dep, void *rockp,
1561 smb_findShare_rock_t * vrock = (smb_findShare_rock_t *) rockp;
1562 if (!strnicmp(dep->name, vrock->shareName, 12)) {
1563 if(!stricmp(dep->name, vrock->shareName))
1564 matchType = SMB_FINDSHARE_EXACT_MATCH;
1566 matchType = SMB_FINDSHARE_PARTIAL_MATCH;
1567 if(vrock->match) free(vrock->match);
1568 vrock->match = strdup(dep->name);
1569 vrock->matchType = matchType;
1571 if(matchType == SMB_FINDSHARE_EXACT_MATCH)
1572 return CM_ERROR_STOPNOW;
1578 /* find a shareName in the table of submounts */
1579 int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName,
1583 char pathName[1024];
1590 DWORD allSubmount = 1;
1592 /* if allSubmounts == 0, only return the //mountRoot/all share
1593 * if in fact it has been been created in the subMounts table.
1594 * This is to allow sites that want to restrict access to the
1597 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1598 0, KEY_QUERY_VALUE, &parmKey);
1599 if (code == ERROR_SUCCESS) {
1600 len = sizeof(allSubmount);
1601 code = RegQueryValueEx(parmKey, "AllSubmount", NULL, NULL,
1602 (BYTE *) &allSubmount, &len);
1603 if (code != ERROR_SUCCESS) {
1606 RegCloseKey (parmKey);
1609 if (allSubmount && _stricmp(shareName, "all") == 0) {
1614 /* In case, the all share is disabled we need to still be able
1615 * to handle ioctl requests
1617 if (_stricmp(shareName, "ioctl$") == 0) {
1618 *pathNamep = strdup("/.__ioctl__");
1622 if (_stricmp(shareName, "IPC$") == 0 ||
1623 _stricmp(shareName, SMB_IOCTL_FILENAME_NOSLASH) == 0 ||
1624 _stricmp(shareName, "DESKTOP.INI") == 0
1630 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts",
1631 0, KEY_QUERY_VALUE, &parmKey);
1632 if (code == ERROR_SUCCESS) {
1633 len = sizeof(pathName);
1634 code = RegQueryValueEx(parmKey, shareName, NULL, NULL,
1635 (BYTE *) pathName, &len);
1636 if (code != ERROR_SUCCESS)
1638 RegCloseKey (parmKey);
1642 if (len != 0 && len != sizeof(pathName) - 1) {
1643 /* We can accept either unix or PC style AFS pathnames. Convert
1644 * Unix-style to PC style here for internal use.
1647 if (strncmp(p, cm_mountRoot, strlen(cm_mountRoot)) == 0)
1648 p += strlen(cm_mountRoot); /* skip mount path */
1651 if (*q == '/') *q = '\\'; /* change to \ */
1657 if (var = smb_stristr(p, VNUserName)) {
1658 if (uidp && uidp->unp)
1659 smb_subst(p, var, sizeof(VNUserName),uidp->unp->name);
1661 smb_subst(p, var, sizeof(VNUserName)," ");
1663 else if (var = smb_stristr(p, VNLCUserName))
1665 if (uidp && uidp->unp)
1666 strcpy(temp, uidp->unp->name);
1670 smb_subst(p, var, sizeof(VNLCUserName), temp);
1672 else if (var = smb_stristr(p, VNComputerName))
1674 sizeTemp = sizeof(temp);
1675 GetComputerName((LPTSTR)temp, &sizeTemp);
1676 smb_subst(p, var, sizeof(VNComputerName), temp);
1678 else if (var = smb_stristr(p, VNLCComputerName))
1680 sizeTemp = sizeof(temp);
1681 GetComputerName((LPTSTR)temp, &sizeTemp);
1683 smb_subst(p, var, sizeof(VNLCComputerName), temp);
1688 *pathNamep = strdup(p);
1693 /* First lookup shareName in root.afs */
1695 smb_findShare_rock_t vrock;
1697 char * p = shareName;
1700 /* attempt to locate a partial match in root.afs. This is because
1701 when using the ANSI RAP calls, the share name is limited to 13 chars
1702 and hence is truncated. Of course we prefer exact matches. */
1704 thyper.HighPart = 0;
1707 vrock.shareName = shareName;
1709 vrock.matchType = 0;
1711 cm_HoldSCache(cm_data.rootSCachep);
1712 code = cm_ApplyDir(cm_data.rootSCachep, smb_FindShareProc, &vrock, &thyper,
1713 (uidp? (uidp->unp ? uidp->unp->userp : NULL) : NULL), &req, NULL);
1714 cm_ReleaseSCache(cm_data.rootSCachep);
1716 if (vrock.matchType) {
1717 sprintf(pathName,"/%s/",vrock.match);
1718 *pathNamep = strdup(strlwr(pathName));
1723 /* if we get here, there was no match for the share in root.afs */
1724 /* so try to create \\<netbiosName>\<cellname> */
1729 /* Get the full name for this cell */
1730 code = cm_SearchCellFile(p, temp, 0, 0);
1731 #ifdef AFS_AFSDB_ENV
1732 if (code && cm_dnsEnabled) {
1734 code = cm_SearchCellByDNS(p, temp, &ttl, 0, 0);
1737 /* construct the path */
1739 sprintf(pathName,rw ? "/.%s/" : "/%s/",temp);
1740 *pathNamep = strdup(strlwr(pathName));
1749 /* Client-side offline caching policy types */
1750 #define CSC_POLICY_MANUAL 0
1751 #define CSC_POLICY_DOCUMENTS 1
1752 #define CSC_POLICY_PROGRAMS 2
1753 #define CSC_POLICY_DISABLE 3
1755 int smb_FindShareCSCPolicy(char *shareName)
1761 int retval = CSC_POLICY_MANUAL;
1763 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
1764 AFSREG_CLT_OPENAFS_SUBKEY "\\CSCPolicy",
1767 REG_OPTION_NON_VOLATILE,
1773 len = sizeof(policy);
1774 if ( RegQueryValueEx( hkCSCPolicy, shareName, 0, &dwType, policy, &len ) ||
1776 retval = stricmp("all",shareName) ? CSC_POLICY_MANUAL : CSC_POLICY_DISABLE;
1778 else if (stricmp(policy, "documents") == 0)
1780 retval = CSC_POLICY_DOCUMENTS;
1782 else if (stricmp(policy, "programs") == 0)
1784 retval = CSC_POLICY_PROGRAMS;
1786 else if (stricmp(policy, "disable") == 0)
1788 retval = CSC_POLICY_DISABLE;
1791 RegCloseKey(hkCSCPolicy);
1795 /* find a dir search structure by cookie value, and return it held.
1796 * Must be called with smb_globalLock held.
1798 smb_dirSearch_t *smb_FindDirSearchNoLock(long cookie)
1800 smb_dirSearch_t *dsp;
1802 for (dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) {
1803 if (dsp->cookie == cookie) {
1804 if (dsp != smb_firstDirSearchp) {
1805 /* move to head of LRU queue, too, if we're not already there */
1806 if (smb_lastDirSearchp == (smb_dirSearch_t *) &dsp->q)
1807 smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&dsp->q);
1808 osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
1809 osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
1810 if (!smb_lastDirSearchp)
1811 smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
1813 lock_ObtainMutex(&dsp->mx);
1815 lock_ReleaseMutex(&dsp->mx);
1821 osi_Log1(smb_logp,"smb_FindDirSearch(%d) == NULL",cookie);
1822 for (dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) {
1823 osi_Log1(smb_logp,"... valid id: %d", dsp->cookie);
1829 void smb_DeleteDirSearch(smb_dirSearch_t *dsp)
1831 lock_ObtainWrite(&smb_globalLock);
1832 lock_ObtainMutex(&dsp->mx);
1833 dsp->flags |= SMB_DIRSEARCH_DELETE;
1834 if (dsp->scp != NULL) {
1835 lock_ObtainMutex(&dsp->scp->mx);
1836 if (dsp->flags & SMB_DIRSEARCH_BULKST) {
1837 dsp->flags &= ~SMB_DIRSEARCH_BULKST;
1838 dsp->scp->flags &= ~CM_SCACHEFLAG_BULKSTATTING;
1839 dsp->scp->bulkStatProgress = hzero;
1841 lock_ReleaseMutex(&dsp->scp->mx);
1843 lock_ReleaseMutex(&dsp->mx);
1844 lock_ReleaseWrite(&smb_globalLock);
1847 /* Must be called with the smb_globalLock held */
1848 void smb_ReleaseDirSearchNoLock(smb_dirSearch_t *dsp)
1850 cm_scache_t *scp = NULL;
1852 lock_ObtainMutex(&dsp->mx);
1853 osi_assert(dsp->refCount-- > 0);
1854 if (dsp->refCount == 0 && (dsp->flags & SMB_DIRSEARCH_DELETE)) {
1855 if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp)
1856 smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q);
1857 osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
1858 lock_ReleaseMutex(&dsp->mx);
1859 lock_FinalizeMutex(&dsp->mx);
1861 osi_Log2(afsd_logp,"smb_ReleaseDirSearch dsp 0x%p scp 0x%p", dsp, scp);
1864 lock_ReleaseMutex(&dsp->mx);
1866 /* do this now to avoid spurious locking hierarchy creation */
1868 cm_ReleaseSCache(scp);
1871 void smb_ReleaseDirSearch(smb_dirSearch_t *dsp)
1873 lock_ObtainWrite(&smb_globalLock);
1874 smb_ReleaseDirSearchNoLock(dsp);
1875 lock_ReleaseWrite(&smb_globalLock);
1878 /* find a dir search structure by cookie value, and return it held */
1879 smb_dirSearch_t *smb_FindDirSearch(long cookie)
1881 smb_dirSearch_t *dsp;
1883 lock_ObtainWrite(&smb_globalLock);
1884 dsp = smb_FindDirSearchNoLock(cookie);
1885 lock_ReleaseWrite(&smb_globalLock);
1889 /* GC some dir search entries, in the address space expected by the specific protocol.
1890 * Must be called with smb_globalLock held; release the lock temporarily.
1892 #define SMB_DIRSEARCH_GCMAX 10 /* how many at once */
1893 void smb_GCDirSearches(int isV3)
1895 smb_dirSearch_t *prevp;
1896 smb_dirSearch_t *tp;
1897 smb_dirSearch_t *victimsp[SMB_DIRSEARCH_GCMAX];
1901 victimCount = 0; /* how many have we got so far */
1902 for (tp = smb_lastDirSearchp; tp; tp=prevp) {
1903 /* we'll move tp from queue, so
1906 prevp = (smb_dirSearch_t *) osi_QPrev(&tp->q);
1907 /* if no one is using this guy, and we're either in the new protocol,
1908 * or we're in the old one and this is a small enough ID to be useful
1909 * to the old protocol, GC this guy.
1911 if (tp->refCount == 0 && (isV3 || tp->cookie <= 255)) {
1912 /* hold and delete */
1913 lock_ObtainMutex(&tp->mx);
1914 tp->flags |= SMB_DIRSEARCH_DELETE;
1915 lock_ReleaseMutex(&tp->mx);
1916 victimsp[victimCount++] = tp;
1920 /* don't do more than this */
1921 if (victimCount >= SMB_DIRSEARCH_GCMAX)
1925 /* now release them */
1926 for (i = 0; i < victimCount; i++) {
1927 smb_ReleaseDirSearchNoLock(victimsp[i]);
1931 /* function for allocating a dir search entry. We need these to remember enough context
1932 * since we don't get passed the path from call to call during a directory search.
1934 * Returns a held dir search structure, and bumps the reference count on the vnode,
1935 * since it saves a pointer to the vnode.
1937 smb_dirSearch_t *smb_NewDirSearch(int isV3)
1939 smb_dirSearch_t *dsp;
1945 lock_ObtainWrite(&smb_globalLock);
1948 /* what's the biggest ID allowed in this version of the protocol */
1949 maxAllowed = isV3 ? 65535 : 255;
1950 if (smb_dirSearchCounter > maxAllowed)
1951 smb_dirSearchCounter = 1;
1953 start = smb_dirSearchCounter;
1956 /* twice so we have enough tries to find guys we GC after one pass;
1957 * 10 extra is just in case I mis-counted.
1959 if (++counter > 2*maxAllowed+10)
1960 osi_panic("afsd: dir search cookie leak", __FILE__, __LINE__);
1962 if (smb_dirSearchCounter > maxAllowed) {
1963 smb_dirSearchCounter = 1;
1965 if (smb_dirSearchCounter == start) {
1967 smb_GCDirSearches(isV3);
1970 dsp = smb_FindDirSearchNoLock(smb_dirSearchCounter);
1972 /* don't need to watch for refcount zero and deleted, since
1973 * we haven't dropped the global lock.
1975 lock_ObtainMutex(&dsp->mx);
1977 lock_ReleaseMutex(&dsp->mx);
1978 ++smb_dirSearchCounter;
1982 dsp = malloc(sizeof(*dsp));
1983 memset(dsp, 0, sizeof(*dsp));
1984 dsp->cookie = smb_dirSearchCounter;
1985 ++smb_dirSearchCounter;
1987 lock_InitializeMutex(&dsp->mx, "cm_dirSearch_t");
1988 dsp->lastTime = osi_Time();
1989 osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
1990 if (!smb_lastDirSearchp)
1991 smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
1994 lock_ReleaseWrite(&smb_globalLock);
1998 static smb_packet_t *GetPacket(void)
2002 lock_ObtainWrite(&smb_globalLock);
2003 tbp = smb_packetFreeListp;
2005 smb_packetFreeListp = tbp->nextp;
2006 lock_ReleaseWrite(&smb_globalLock);
2008 tbp = calloc(65540,1);
2009 tbp->magic = SMB_PACKETMAGIC;
2012 tbp->resumeCode = 0;
2018 tbp->ncb_length = 0;
2023 osi_assert(tbp->magic == SMB_PACKETMAGIC);
2028 smb_packet_t *smb_CopyPacket(smb_packet_t *pkt)
2032 memcpy(tbp, pkt, sizeof(smb_packet_t));
2033 tbp->wctp = tbp->data + (unsigned int)(pkt->wctp - pkt->data);
2035 smb_HoldVC(tbp->vcp);
2039 static NCB *GetNCB(void)
2044 lock_ObtainWrite(&smb_globalLock);
2045 tbp = smb_ncbFreeListp;
2047 smb_ncbFreeListp = tbp->nextp;
2048 lock_ReleaseWrite(&smb_globalLock);
2050 tbp = calloc(sizeof(*tbp),1);
2051 tbp->magic = SMB_NCBMAGIC;
2054 osi_assert(tbp->magic == SMB_NCBMAGIC);
2056 memset(&tbp->ncb, 0, sizeof(NCB));
2061 void smb_FreePacket(smb_packet_t *tbp)
2063 smb_vc_t * vcp = NULL;
2064 osi_assert(tbp->magic == SMB_PACKETMAGIC);
2066 lock_ObtainWrite(&smb_globalLock);
2067 tbp->nextp = smb_packetFreeListp;
2068 smb_packetFreeListp = tbp;
2069 tbp->magic = SMB_PACKETMAGIC;
2073 tbp->resumeCode = 0;
2079 tbp->ncb_length = 0;
2081 lock_ReleaseWrite(&smb_globalLock);
2087 static void FreeNCB(NCB *bufferp)
2091 tbp = (smb_ncb_t *) bufferp;
2092 osi_assert(tbp->magic == SMB_NCBMAGIC);
2094 lock_ObtainWrite(&smb_globalLock);
2095 tbp->nextp = smb_ncbFreeListp;
2096 smb_ncbFreeListp = tbp;
2097 lock_ReleaseWrite(&smb_globalLock);
2100 /* get a ptr to the data part of a packet, and its count */
2101 unsigned char *smb_GetSMBData(smb_packet_t *smbp, int *nbytesp)
2105 unsigned char *afterParmsp;
2107 parmBytes = *smbp->wctp << 1;
2108 afterParmsp = smbp->wctp + parmBytes + 1;
2110 dataBytes = afterParmsp[0] + (afterParmsp[1]<<8);
2111 if (nbytesp) *nbytesp = dataBytes;
2113 /* don't forget to skip the data byte count, since it follows
2114 * the parameters; that's where the "2" comes from below.
2116 return (unsigned char *) (afterParmsp + 2);
2119 /* must set all the returned parameters before playing around with the
2120 * data region, since the data region is located past the end of the
2121 * variable number of parameters.
2123 void smb_SetSMBDataLength(smb_packet_t *smbp, unsigned int dsize)
2125 unsigned char *afterParmsp;
2127 afterParmsp = smbp->wctp + ((*smbp->wctp)<<1) + 1;
2129 *afterParmsp++ = dsize & 0xff;
2130 *afterParmsp = (dsize>>8) & 0xff;
2133 /* return the parm'th parameter in the smbp packet */
2134 unsigned int smb_GetSMBParm(smb_packet_t *smbp, int parm)
2137 unsigned char *parmDatap;
2139 parmCount = *smbp->wctp;
2141 if (parm >= parmCount) {
2144 sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
2145 parm, parmCount, smbp->ncb_length);
2146 osi_Log3(smb_logp,"Bad SMB param %d out of %d, ncb len %d",
2147 parm, parmCount, smbp->ncb_length);
2148 LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM,
2149 __FILE__, __LINE__, parm, parmCount, smbp->ncb_length);
2150 osi_panic(s, __FILE__, __LINE__);
2152 parmDatap = smbp->wctp + (2*parm) + 1;
2154 return parmDatap[0] + (parmDatap[1] << 8);
2157 /* return the parm'th parameter in the smbp packet */
2158 unsigned int smb_GetSMBParmLong(smb_packet_t *smbp, int parm)
2161 unsigned char *parmDatap;
2163 parmCount = *smbp->wctp;
2165 if (parm + 1 >= parmCount) {
2168 sprintf(s, "Bad SMB param %d out of %d, ncb len %d",
2169 parm, parmCount, smbp->ncb_length);
2170 osi_Log3(smb_logp,"Bad SMB param %d out of %d, ncb len %d",
2171 parm, parmCount, smbp->ncb_length);
2172 LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM,
2173 __FILE__, __LINE__, parm, parmCount, smbp->ncb_length);
2174 osi_panic(s, __FILE__, __LINE__);
2176 parmDatap = smbp->wctp + (2*parm) + 1;
2178 return parmDatap[0] + (parmDatap[1] << 8) + (parmDatap[2] << 16) + (parmDatap[3] << 24);
2181 /* return the parm'th parameter in the smbp packet */
2182 unsigned int smb_GetSMBOffsetParm(smb_packet_t *smbp, int parm, int offset)
2185 unsigned char *parmDatap;
2187 parmCount = *smbp->wctp;
2189 if (parm * 2 + offset >= parmCount * 2) {
2192 sprintf(s, "Bad SMB param %d offset %d out of %d, ncb len %d",
2193 parm, offset, parmCount, smbp->ncb_length);
2194 LogEvent(EVENTLOG_ERROR_TYPE, MSG_BAD_SMB_PARAM_WITH_OFFSET,
2195 __FILE__, __LINE__, parm, offset, parmCount, smbp->ncb_length);
2196 osi_Log4(smb_logp, "Bad SMB param %d offset %d out of %d, ncb len %d",
2197 parm, offset, parmCount, smbp->ncb_length);
2198 osi_panic(s, __FILE__, __LINE__);
2200 parmDatap = smbp->wctp + (2*parm) + 1 + offset;
2202 return parmDatap[0] + (parmDatap[1] << 8);
2205 void smb_SetSMBParm(smb_packet_t *smbp, int slot, unsigned int parmValue)
2209 /* make sure we have enough slots */
2210 if (*smbp->wctp <= slot)
2211 *smbp->wctp = slot+1;
2213 parmDatap = smbp->wctp + 2*slot + 1 + smbp->oddByte;
2214 *parmDatap++ = parmValue & 0xff;
2215 *parmDatap = (parmValue>>8) & 0xff;
2218 void smb_SetSMBParmLong(smb_packet_t *smbp, int slot, unsigned int parmValue)
2222 /* make sure we have enough slots */
2223 if (*smbp->wctp <= slot)
2224 *smbp->wctp = slot+2;
2226 parmDatap = smbp->wctp + 2*slot + 1 + smbp->oddByte;
2227 *parmDatap++ = parmValue & 0xff;
2228 *parmDatap++ = (parmValue>>8) & 0xff;
2229 *parmDatap++ = (parmValue>>16) & 0xff;
2230 *parmDatap = (parmValue>>24) & 0xff;
2233 void smb_SetSMBParmDouble(smb_packet_t *smbp, int slot, char *parmValuep)
2238 /* make sure we have enough slots */
2239 if (*smbp->wctp <= slot)
2240 *smbp->wctp = slot+4;
2242 parmDatap = smbp->wctp + 2*slot + 1 + smbp->oddByte;
2244 *parmDatap++ = *parmValuep++;
2247 void smb_SetSMBParmByte(smb_packet_t *smbp, int slot, unsigned int parmValue)
2251 /* make sure we have enough slots */
2252 if (*smbp->wctp <= slot) {
2253 if (smbp->oddByte) {
2255 *smbp->wctp = slot+1;
2260 parmDatap = smbp->wctp + 2*slot + 1 + (1 - smbp->oddByte);
2261 *parmDatap++ = parmValue & 0xff;
2264 void smb_StripLastComponent(char *outPathp, char **lastComponentp, char *inPathp)
2268 lastSlashp = strrchr(inPathp, '\\');
2270 *lastComponentp = lastSlashp;
2273 if (inPathp == lastSlashp)
2275 *outPathp++ = *inPathp++;
2284 unsigned char *smb_ParseASCIIBlock(unsigned char *inp, char **chainpp)
2289 *chainpp = inp + strlen(inp) + 1; /* skip over null-terminated string */
2294 unsigned char *smb_ParseVblBlock(unsigned char *inp, char **chainpp, int *lengthp)
2300 tlen = inp[0] + (inp[1]<<8);
2301 inp += 2; /* skip length field */
2304 *chainpp = inp + tlen;
2313 /* format a packet as a response */
2314 void smb_FormatResponsePacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *op)
2319 outp = (smb_t *) op;
2321 /* zero the basic structure through the smb_wct field, and zero the data
2322 * size field, assuming that wct stays zero; otherwise, you have to
2323 * explicitly set the data size field, too.
2325 inSmbp = (smb_t *) inp;
2326 memset(outp, 0, sizeof(smb_t)+2);
2332 outp->com = inSmbp->com;
2333 outp->tid = inSmbp->tid;
2334 outp->pid = inSmbp->pid;
2335 outp->uid = inSmbp->uid;
2336 outp->mid = inSmbp->mid;
2337 outp->res[0] = inSmbp->res[0];
2338 outp->res[1] = inSmbp->res[1];
2339 op->inCom = inSmbp->com;
2341 outp->reb = SMB_FLAGS_SERVER_TO_CLIENT | SMB_FLAGS_CANONICAL_PATHNAMES;
2342 outp->flg2 = SMB_FLAGS2_KNOWS_LONG_NAMES;
2344 /* copy fields in generic packet area */
2345 op->wctp = &outp->wct;
2348 /* send a (probably response) packet; vcp tells us to whom to send it.
2349 * we compute the length by looking at wct and bcc fields.
2351 void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp)
2365 memset((char *)ncbp, 0, sizeof(NCB));
2367 extra = 2 * (*inp->wctp); /* space used by parms, in bytes */
2368 tp = inp->wctp + 1+ extra; /* points to count of data bytes */
2369 extra += tp[0] + (tp[1]<<8);
2370 extra += (unsigned int)(inp->wctp - inp->data); /* distance to last wct field */
2371 extra += 3; /* wct and length fields */
2373 ncbp->ncb_length = extra; /* bytes to send */
2374 ncbp->ncb_lsn = (unsigned char) vcp->lsn; /* vc to use */
2375 ncbp->ncb_lana_num = vcp->lana;
2376 ncbp->ncb_command = NCBSEND; /* op means send data */
2377 ncbp->ncb_buffer = (char *) inp;/* packet */
2378 code = Netbios(ncbp);
2381 const char * s = ncb_error_string(code);
2382 osi_Log2(smb_logp, "SendPacket failure code %d \"%s\"", code, s);
2383 LogEvent(EVENTLOG_WARNING_TYPE, MSG_SMB_SEND_PACKET_FAILURE, s);
2385 lock_ObtainMutex(&vcp->mx);
2386 if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) {
2387 osi_Log2(smb_logp, "marking dead vcp 0x%x, user struct 0x%x",
2389 vcp->flags |= SMB_VCFLAG_ALREADYDEAD;
2390 lock_ReleaseMutex(&vcp->mx);
2391 lock_ObtainWrite(&smb_globalLock);
2392 dead_sessions[vcp->session] = TRUE;
2393 lock_ReleaseWrite(&smb_globalLock);
2394 smb_CleanupDeadVC(vcp);
2396 lock_ReleaseMutex(&vcp->mx);
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;
2779 char *rawBuf = NULL;
2784 fd = smb_GetSMBParm(inp, 0);
2785 count = smb_GetSMBParm(inp, 3);
2786 minCount = smb_GetSMBParm(inp, 4);
2787 offset.LowPart = smb_GetSMBParm(inp, 1) | (smb_GetSMBParm(inp, 2) << 16);
2789 if (*inp->wctp == 10) {
2790 /* we were sent a request with 64-bit file offsets */
2791 #ifdef AFS_LARGEFILES
2792 offset.HighPart = smb_GetSMBParm(inp, 8) | (smb_GetSMBParm(inp, 9) << 16);
2794 if (LargeIntegerLessThanZero(offset)) {
2795 osi_Log0(smb_logp, "smb_ReceiveCoreReadRaw received negative 64-bit offset");
2799 if ((smb_GetSMBParm(inp, 8) | (smb_GetSMBParm(inp, 9) << 16)) != 0) {
2800 osi_Log0(smb_logp, "smb_ReceiveCoreReadRaw received 64-bit file offset. Dropping request.");
2803 offset.HighPart = 0;
2807 /* we were sent a request with 32-bit file offsets */
2808 offset.HighPart = 0;
2811 osi_Log4(smb_logp, "smb_ReceieveCoreReadRaw fd %d, off 0x%x:%08x, size 0x%x",
2812 fd, offset.HighPart, offset.LowPart, count);
2814 fidp = smb_FindFID(vcp, fd, 0);
2818 pid = ((smb_t *) inp)->pid;
2820 LARGE_INTEGER LOffset, LLength;
2823 key = cm_GenerateKey(vcp->vcID, pid, fd);
2825 LOffset.HighPart = offset.HighPart;
2826 LOffset.LowPart = offset.LowPart;
2827 LLength.HighPart = 0;
2828 LLength.LowPart = count;
2830 lock_ObtainMutex(&fidp->scp->mx);
2831 code = cm_LockCheckRead(fidp->scp, LOffset, LLength, key);
2832 lock_ReleaseMutex(&fidp->scp->mx);
2838 lock_ObtainMutex(&smb_RawBufLock);
2840 /* Get a raw buf, from head of list */
2841 rawBuf = smb_RawBufs;
2842 smb_RawBufs = *(char **)smb_RawBufs;
2844 lock_ReleaseMutex(&smb_RawBufLock);
2848 lock_ObtainMutex(&fidp->mx);
2849 if (fidp->flags & SMB_FID_IOCTL)
2851 lock_ReleaseMutex(&fidp->mx);
2852 rc = smb_IoctlReadRaw(fidp, vcp, inp, outp);
2854 /* Give back raw buffer */
2855 lock_ObtainMutex(&smb_RawBufLock);
2856 *((char **) rawBuf) = smb_RawBufs;
2858 smb_RawBufs = rawBuf;
2859 lock_ReleaseMutex(&smb_RawBufLock);
2862 smb_ReleaseFID(fidp);
2865 lock_ReleaseMutex(&fidp->mx);
2867 userp = smb_GetUserFromVCP(vcp, inp);
2869 code = smb_ReadData(fidp, &offset, count, rawBuf, userp, &finalCount);
2875 cm_ReleaseUser(userp);
2878 smb_ReleaseFID(fidp);
2882 memset((char *)ncbp, 0, sizeof(NCB));
2884 ncbp->ncb_length = (unsigned short) finalCount;
2885 ncbp->ncb_lsn = (unsigned char) vcp->lsn;
2886 ncbp->ncb_lana_num = vcp->lana;
2887 ncbp->ncb_command = NCBSEND;
2888 ncbp->ncb_buffer = rawBuf;
2890 code = Netbios(ncbp);
2892 osi_Log1(smb_logp, "ReadRaw send failure code %d", code);
2895 /* Give back raw buffer */
2896 lock_ObtainMutex(&smb_RawBufLock);
2897 *((char **) rawBuf) = smb_RawBufs;
2899 smb_RawBufs = rawBuf;
2900 lock_ReleaseMutex(&smb_RawBufLock);
2906 long smb_ReceiveCoreLockRecord(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
2908 osi_Log1(smb_logp, "SMB receive core lock record (not implemented); %d + 1 ongoing ops",
2913 long smb_ReceiveCoreUnlockRecord(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
2915 osi_Log1(smb_logp, "SMB receive core unlock record (not implemented); %d + 1 ongoing ops",
2920 long smb_ReceiveNegotiate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
2927 int VistaProtoIndex;
2928 int protoIndex; /* index we're using */
2933 char protocol_array[10][1024]; /* protocol signature of the client */
2934 int caps; /* capabilities */
2937 TIME_ZONE_INFORMATION tzi;
2939 osi_Log1(smb_logp, "SMB receive negotiate; %d + 1 ongoing ops",
2942 namep = smb_GetSMBData(inp, &dbytes);
2945 coreProtoIndex = -1; /* not found */
2948 VistaProtoIndex = -1;
2949 while(namex < dbytes) {
2950 osi_Log1(smb_logp, "Protocol %s",
2951 osi_LogSaveString(smb_logp, namep+1));
2952 strcpy(protocol_array[tcounter], namep+1);
2954 /* namep points at the first protocol, or really, a 0x02
2955 * byte preceding the null-terminated ASCII name.
2957 if (strcmp("PC NETWORK PROGRAM 1.0", namep+1) == 0) {
2958 coreProtoIndex = tcounter;
2960 else if (smb_useV3 && strcmp("LM1.2X002", namep+1) == 0) {
2961 v3ProtoIndex = tcounter;
2963 else if (smb_useV3 && strcmp("NT LM 0.12", namep+1) == 0) {
2964 NTProtoIndex = tcounter;
2966 else if (smb_useV3 && strcmp("SMB 2.001", namep+1) == 0) {
2967 VistaProtoIndex = tcounter;
2970 /* compute size of protocol entry */
2971 entryLength = (int)strlen(namep+1);
2972 entryLength += 2; /* 0x02 bytes and null termination */
2974 /* advance over this protocol entry */
2975 namex += entryLength;
2976 namep += entryLength;
2977 tcounter++; /* which proto entry we're looking at */
2980 lock_ObtainMutex(&vcp->mx);
2982 if (VistaProtoIndex != -1) {
2983 protoIndex = VistaProtoIndex;
2984 vcp->flags |= (SMB_VCFLAG_USENT | SMB_VCFLAG_USEV3);
2987 if (NTProtoIndex != -1) {
2988 protoIndex = NTProtoIndex;
2989 vcp->flags |= (SMB_VCFLAG_USENT | SMB_VCFLAG_USEV3);
2991 else if (v3ProtoIndex != -1) {
2992 protoIndex = v3ProtoIndex;
2993 vcp->flags |= SMB_VCFLAG_USEV3;
2995 else if (coreProtoIndex != -1) {
2996 protoIndex = coreProtoIndex;
2997 vcp->flags |= SMB_VCFLAG_USECORE;
2999 else protoIndex = -1;
3000 lock_ReleaseMutex(&vcp->mx);
3002 if (protoIndex == -1)
3003 return CM_ERROR_INVAL;
3004 else if (VistaProtoIndex != 1 || NTProtoIndex != -1) {
3005 smb_SetSMBParm(outp, 0, protoIndex);
3006 if (smb_authType != SMB_AUTH_NONE) {
3007 smb_SetSMBParmByte(outp, 1,
3008 NEGOTIATE_SECURITY_USER_LEVEL |
3009 NEGOTIATE_SECURITY_CHALLENGE_RESPONSE); /* user level security, challenge response */
3011 smb_SetSMBParmByte(outp, 1, 0); /* share level auth with plaintext password. */
3013 smb_SetSMBParm(outp, 1, smb_maxMpxRequests); /* max multiplexed requests */
3014 smb_SetSMBParm(outp, 2, smb_maxVCPerServer); /* max VCs per consumer/server connection */
3015 smb_SetSMBParmLong(outp, 3, SMB_PACKETSIZE); /* xmit buffer size */
3016 smb_SetSMBParmLong(outp, 5, SMB_MAXRAWSIZE); /* raw buffer size */
3017 /* The session key is not a well documented field however most clients
3018 * will echo back the session key to the server. Currently we are using
3019 * the same value for all sessions. We should generate a random value
3020 * and store it into the vcp
3022 smb_SetSMBParm(outp, 7, 1); /* next 2: session key */
3023 smb_SetSMBParm(outp, 8, 1);
3025 * Tried changing the capabilities to support for W2K - defect 117695
3026 * Maybe something else needs to be changed here?
3030 smb_SetSMBParmLong(outp, 9, 0x43fd);
3032 smb_SetSMBParmLong(outp, 9, 0x251);
3035 * 32-bit error codes *
3040 caps = NTNEGOTIATE_CAPABILITY_NTSTATUS |
3042 NTNEGOTIATE_CAPABILITY_DFS |
3044 #ifdef AFS_LARGEFILES
3045 NTNEGOTIATE_CAPABILITY_LARGEFILES |
3047 NTNEGOTIATE_CAPABILITY_NTFIND |
3048 NTNEGOTIATE_CAPABILITY_RAWMODE |
3049 NTNEGOTIATE_CAPABILITY_NTSMB;
3051 if ( smb_authType == SMB_AUTH_EXTENDED )
3052 caps |= NTNEGOTIATE_CAPABILITY_EXTENDED_SECURITY;
3054 smb_SetSMBParmLong(outp, 9, caps);
3056 smb_SearchTimeFromUnixTime(&dosTime, unixTime);
3057 smb_SetSMBParmLong(outp, 11, LOWORD(dosTime));/* server time */
3058 smb_SetSMBParmLong(outp, 13, HIWORD(dosTime));/* server date */
3060 GetTimeZoneInformation(&tzi);
3061 smb_SetSMBParm(outp, 15, (unsigned short) tzi.Bias); /* server tzone */
3063 if (smb_authType == SMB_AUTH_NTLM) {
3064 smb_SetSMBParmByte(outp, 16, MSV1_0_CHALLENGE_LENGTH);/* Encryption key length */
3065 smb_SetSMBDataLength(outp, MSV1_0_CHALLENGE_LENGTH + smb_ServerDomainNameLength);
3066 /* paste in encryption key */
3067 datap = smb_GetSMBData(outp, NULL);
3068 memcpy(datap,vcp->encKey,MSV1_0_CHALLENGE_LENGTH);
3069 /* and the faux domain name */
3070 strcpy(datap + MSV1_0_CHALLENGE_LENGTH,smb_ServerDomainName);
3071 } else if ( smb_authType == SMB_AUTH_EXTENDED ) {
3075 smb_SetSMBParmByte(outp, 16, 0); /* Encryption key length */
3077 smb_NegotiateExtendedSecurity(&secBlob, &secBlobLength);
3079 smb_SetSMBDataLength(outp, secBlobLength + sizeof(smb_ServerGUID));
3081 datap = smb_GetSMBData(outp, NULL);
3082 memcpy(datap, &smb_ServerGUID, sizeof(smb_ServerGUID));
3085 datap += sizeof(smb_ServerGUID);
3086 memcpy(datap, secBlob, secBlobLength);
3090 smb_SetSMBParmByte(outp, 16, 0); /* Encryption key length */
3091 smb_SetSMBDataLength(outp, 0); /* Perhaps we should specify 8 bytes anyway */
3094 else if (v3ProtoIndex != -1) {
3095 smb_SetSMBParm(outp, 0, protoIndex);
3097 /* NOTE: Extended authentication cannot be negotiated with v3
3098 * therefore we fail over to NTLM
3100 if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
3101 smb_SetSMBParm(outp, 1,
3102 NEGOTIATE_SECURITY_USER_LEVEL |
3103 NEGOTIATE_SECURITY_CHALLENGE_RESPONSE); /* user level security, challenge response */
3105 smb_SetSMBParm(outp, 1, 0); /* share level auth with clear password */
3107 smb_SetSMBParm(outp, 2, SMB_PACKETSIZE);
3108 smb_SetSMBParm(outp, 3, smb_maxMpxRequests); /* max multiplexed requests */
3109 smb_SetSMBParm(outp, 4, smb_maxVCPerServer); /* max VCs per consumer/server connection */
3110 smb_SetSMBParm(outp, 5, 0); /* no support of block mode for read or write */
3111 smb_SetSMBParm(outp, 6, 1); /* next 2: session key */
3112 smb_SetSMBParm(outp, 7, 1);
3114 smb_SearchTimeFromUnixTime(&dosTime, unixTime);
3115 smb_SetSMBParm(outp, 8, LOWORD(dosTime)); /* server time */
3116 smb_SetSMBParm(outp, 9, HIWORD(dosTime)); /* server date */
3118 GetTimeZoneInformation(&tzi);
3119 smb_SetSMBParm(outp, 10, (unsigned short) tzi.Bias); /* server tzone */
3121 /* NOTE: Extended authentication cannot be negotiated with v3
3122 * therefore we fail over to NTLM
3124 if (smb_authType == SMB_AUTH_NTLM || smb_authType == SMB_AUTH_EXTENDED) {
3125 smb_SetSMBParm(outp, 11, MSV1_0_CHALLENGE_LENGTH); /* encryption key length */
3126 smb_SetSMBParm(outp, 12, 0); /* resvd */
3127 smb_SetSMBDataLength(outp, MSV1_0_CHALLENGE_LENGTH + smb_ServerDomainNameLength); /* perhaps should specify 8 bytes anyway */
3128 datap = smb_GetSMBData(outp, NULL);
3129 /* paste in a new encryption key */
3130 memcpy(datap, vcp->encKey, MSV1_0_CHALLENGE_LENGTH);
3131 /* and the faux domain name */
3132 strcpy(datap + MSV1_0_CHALLENGE_LENGTH, smb_ServerDomainName);
3134 smb_SetSMBParm(outp, 11, 0); /* encryption key length */
3135 smb_SetSMBParm(outp, 12, 0); /* resvd */
3136 smb_SetSMBDataLength(outp, 0);
3139 else if (coreProtoIndex != -1) { /* not really supported anymore */
3140 smb_SetSMBParm(outp, 0, protoIndex);
3141 smb_SetSMBDataLength(outp, 0);
3146 void smb_CheckVCs(void)
3148 smb_vc_t * vcp, *nextp;
3149 smb_packet_t * outp = GetPacket();
3152 lock_ObtainWrite(&smb_rctLock);
3153 for ( vcp=smb_allVCsp, nextp=NULL; vcp; vcp = nextp )
3155 if (vcp->magic != SMB_VC_MAGIC)
3156 osi_panic("afsd: invalid smb_vc_t detected in smb_allVCsp",
3157 __FILE__, __LINE__);
3161 if (vcp->flags & SMB_VCFLAG_ALREADYDEAD)
3164 smb_HoldVCNoLock(vcp);
3166 smb_HoldVCNoLock(nextp);
3167 smb_FormatResponsePacket(vcp, NULL, outp);
3168 smbp = (smb_t *)outp;
3169 outp->inCom = smbp->com = 0x2b /* Echo */;
3177 smb_SetSMBParm(outp, 0, 0);
3178 smb_SetSMBDataLength(outp, 0);
3179 lock_ReleaseWrite(&smb_rctLock);
3181 smb_SendPacket(vcp, outp);
3183 lock_ObtainWrite(&smb_rctLock);
3184 smb_ReleaseVCNoLock(vcp);
3186 smb_ReleaseVCNoLock(nextp);
3188 lock_ReleaseWrite(&smb_rctLock);
3189 smb_FreePacket(outp);
3192 void smb_Daemon(void *parmp)
3194 afs_uint32 count = 0;
3195 smb_username_t **unpp;
3198 while(smbShutdownFlag == 0) {
3202 if (smbShutdownFlag == 1)
3205 if ((count % 72) == 0) { /* every five minutes */
3207 time_t old_localZero = smb_localZero;
3209 /* Initialize smb_localZero */
3210 myTime.tm_isdst = -1; /* compute whether on DST or not */
3211 myTime.tm_year = 70;
3217 smb_localZero = mktime(&myTime);
3219 #ifndef USE_NUMERIC_TIME_CONV
3220 smb_CalculateNowTZ();
3221 #endif /* USE_NUMERIC_TIME_CONV */
3222 #ifdef AFS_FREELANCE
3223 if ( smb_localZero != old_localZero )
3224 cm_noteLocalMountPointChange();
3230 /* GC smb_username_t objects that will no longer be used */
3232 lock_ObtainWrite(&smb_rctLock);
3233 for ( unpp=&usernamesp; *unpp; ) {
3235 smb_username_t *unp;
3237 lock_ObtainMutex(&(*unpp)->mx);
3238 if ( (*unpp)->refCount > 0 ||
3239 ((*unpp)->flags & SMB_USERNAMEFLAG_AFSLOGON) ||
3240 !((*unpp)->flags & SMB_USERNAMEFLAG_LOGOFF))
3242 else if (!smb_LogoffTokenTransfer ||
3243 ((*unpp)->last_logoff_t + smb_LogoffTransferTimeout < now))
3245 lock_ReleaseMutex(&(*unpp)->mx);
3253 lock_FinalizeMutex(&unp->mx);
3259 lock_ReleaseWrite(&smb_rctLock);
3260 cm_ReleaseUser(userp);
3261 lock_ObtainWrite(&smb_rctLock);
3264 unpp = &(*unpp)->nextp;
3267 lock_ReleaseWrite(&smb_rctLock);
3269 /* XXX GC dir search entries */
3273 void smb_WaitingLocksDaemon()
3275 smb_waitingLockRequest_t *wlRequest, *nwlRequest;
3276 smb_waitingLock_t *wl, *wlNext;
3279 smb_packet_t *inp, *outp;
3283 while (smbShutdownFlag == 0) {
3284 lock_ObtainWrite(&smb_globalLock);
3285 nwlRequest = smb_allWaitingLocks;
3286 if (nwlRequest == NULL) {
3287 osi_SleepW((LONG_PTR)&smb_allWaitingLocks, &smb_globalLock);
3292 osi_Log0(smb_logp, "smb_WaitingLocksDaemon starting wait lock check");
3299 lock_ObtainWrite(&smb_globalLock);
3301 osi_Log1(smb_logp, " Checking waiting lock request %p", nwlRequest);
3303 wlRequest = nwlRequest;
3304 nwlRequest = (smb_waitingLockRequest_t *) osi_QNext(&wlRequest->q);
3305 lock_ReleaseWrite(&smb_globalLock);
3309 for (wl = wlRequest->locks; wl; wl = (smb_waitingLock_t *) osi_QNext(&wl->q)) {
3310 if (wl->state == SMB_WAITINGLOCKSTATE_DONE)
3313 osi_assert(wl->state != SMB_WAITINGLOCKSTATE_ERROR);
3315 /* wl->state is either _DONE or _WAITING. _ERROR
3316 would no longer be on the queue. */
3317 code = cm_RetryLock( wl->lockp,
3318 !!(wlRequest->vcp->flags & SMB_VCFLAG_ALREADYDEAD) );
3321 wl->state = SMB_WAITINGLOCKSTATE_DONE;
3322 } else if (code != CM_ERROR_WOULDBLOCK) {
3323 wl->state = SMB_WAITINGLOCKSTATE_ERROR;
3328 if (code == CM_ERROR_WOULDBLOCK) {
3331 if (wlRequest->timeRemaining != 0xffffffff
3332 && (wlRequest->timeRemaining -= 1000) < 0)
3344 osi_Log1(smb_logp, "smb_WaitingLocksDaemon discarding lock req %p",
3347 scp = wlRequest->scp;
3348 osi_Log2(afsd_logp,"smb_WaitingLocksDaemon wlRequest 0x%p scp 0x%p", wlRequest, scp);
3352 lock_ObtainMutex(&scp->mx);
3354 for (wl = wlRequest->locks; wl; wl = wlNext) {
3355 wlNext = (smb_waitingLock_t *) osi_QNext(&wl->q);
3357 cm_Unlock(scp, wlRequest->lockType, wl->LOffset,
3358 wl->LLength, wl->key, NULL, &req);
3360 osi_QRemove((osi_queue_t **) &wlRequest->locks, &wl->q);
3365 lock_ReleaseMutex(&scp->mx);
3369 osi_Log1(smb_logp, "smb_WaitingLocksDaemon granting lock req %p",
3372 for (wl = wlRequest->locks; wl; wl = wlNext) {
3373 wlNext = (smb_waitingLock_t *) osi_QNext(&wl->q);
3374 osi_QRemove((osi_queue_t **) &wlRequest->locks, &wl->q);
3379 vcp = wlRequest->vcp;
3380 inp = wlRequest->inp;
3381 outp = wlRequest->outp;
3383 ncbp->ncb_length = inp->ncb_length;
3384 inp->spacep = cm_GetSpace();
3386 /* Remove waitingLock from list */
3387 lock_ObtainWrite(&smb_globalLock);
3388 osi_QRemove((osi_queue_t **)&smb_allWaitingLocks,
3390 lock_ReleaseWrite(&smb_globalLock);
3392 /* Resume packet processing */
3394 smb_SetSMBDataLength(outp, 0);
3395 outp->flags |= SMB_PACKETFLAG_SUSPENDED;
3396 outp->resumeCode = code;
3398 smb_DispatchPacket(vcp, inp, outp, ncbp, NULL);
3401 cm_FreeSpace(inp->spacep);
3402 smb_FreePacket(inp);
3403 smb_FreePacket(outp);
3405 cm_ReleaseSCache(wlRequest->scp);
3408 } while (nwlRequest && smbShutdownFlag == 0);
3413 long smb_ReceiveCoreGetDiskAttributes(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
3415 osi_Log0(smb_logp, "SMB receive get disk attributes");
3417 smb_SetSMBParm(outp, 0, 32000);
3418 smb_SetSMBParm(outp, 1, 64);
3419 smb_SetSMBParm(outp, 2, 1024);
3420 smb_SetSMBParm(outp, 3, 30000);
3421 smb_SetSMBParm(outp, 4, 0);
3422 smb_SetSMBDataLength(outp, 0);
3426 long smb_ReceiveCoreTreeConnect(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *rsp)
3430 unsigned short newTid;
3431 char shareName[256];
3439 osi_Log0(smb_logp, "SMB receive tree connect");
3441 /* parse input parameters */
3442 tp = smb_GetSMBData(inp, NULL);
3443 pathp = smb_ParseASCIIBlock(tp, &tp);
3444 if (smb_StoreAnsiFilenames)
3445 OemToChar(pathp,pathp);
3446 passwordp = smb_ParseASCIIBlock(tp, &tp);
3447 tp = strrchr(pathp, '\\');
3449 return CM_ERROR_BADSMB;
3450 strcpy(shareName, tp+1);
3452 lock_ObtainMutex(&vcp->mx);
3453 newTid = vcp->tidCounter++;
3454 lock_ReleaseMutex(&vcp->mx);
3456 tidp = smb_FindTID(vcp, newTid, SMB_FLAG_CREATE);
3457 uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0);
3458 userp = smb_GetUserFromUID(uidp);
3459 shareFound = smb_FindShare(vcp, uidp, shareName, &sharePath);
3461 smb_ReleaseUID(uidp);
3463 smb_ReleaseTID(tidp);
3464 return CM_ERROR_BADSHARENAME;
3466 lock_ObtainMutex(&tidp->mx);
3467 tidp->userp = userp;
3468 tidp->pathname = sharePath;
3469 lock_ReleaseMutex(&tidp->mx);
3470 smb_ReleaseTID(tidp);
3472 smb_SetSMBParm(rsp, 0, SMB_PACKETSIZE);
3473 smb_SetSMBParm(rsp, 1, newTid);
3474 smb_SetSMBDataLength(rsp, 0);
3476 osi_Log1(smb_logp, "SMB tree connect created ID %d", newTid);
3480 unsigned char *smb_ParseDataBlock(unsigned char *inp, char **chainpp, int *lengthp)
3484 if (*inp++ != 0x1) return NULL;
3485 tlen = inp[0] + (inp[1]<<8);
3486 inp += 2; /* skip length field */
3489 *chainpp = inp + tlen;
3492 if (lengthp) *lengthp = tlen;
3497 /* set maskp to the mask part of the incoming path.
3498 * Mask is 11 bytes long (8.3 with the dot elided).
3499 * Returns true if succeeds with a valid name, otherwise it does
3500 * its best, but returns false.
3502 int smb_Get8Dot3MaskFromPath(unsigned char *maskp, unsigned char *pathp)
3510 /* starts off valid */
3513 /* mask starts out all blanks */
3514 memset(maskp, ' ', 11);
3516 /* find last backslash, or use whole thing if there is none */
3517 tp = strrchr(pathp, '\\');
3518 if (!tp) tp = pathp;
3519 else tp++; /* skip slash */
3523 /* names starting with a dot are illegal */
3524 if (*tp == '.') valid8Dot3 = 0;
3528 if (tc == 0) return valid8Dot3;
3529 if (tc == '.' || tc == '"') break;
3530 if (i < 8) *up++ = tc;
3531 else valid8Dot3 = 0;
3534 /* if we get here, tp point after the dot */
3535 up = maskp+8; /* ext goes here */
3542 if (tc == '.' || tc == '"')
3545 /* copy extension if not too long */
3555 int smb_Match8Dot3Mask(char *unixNamep, char *maskp)
3565 /* XXX redo this, calling smb_V3MatchMask with a converted mask */
3567 valid = smb_Get8Dot3MaskFromPath(umask, unixNamep);
3571 /* otherwise, we have a valid 8.3 name; see if we have a match,
3572 * treating '?' as a wildcard in maskp (but not in the file name).
3574 tp1 = umask; /* real name, in mask format */
3575 tp2 = maskp; /* mask, in mask format */
3576 for(i=0; i<11; i++) {
3577 tc1 = *tp1++; /* char from real name */
3578 tc2 = *tp2++; /* char from mask */
3579 tc1 = (char) cm_foldUpper[(unsigned char)tc1];
3580 tc2 = (char) cm_foldUpper[(unsigned char)tc2];
3583 if (tc2 == '?' && tc1 != ' ')
3590 /* we got a match */
3594 char *smb_FindMask(char *pathp)
3598 tp = strrchr(pathp, '\\'); /* find last slash */
3601 return tp+1; /* skip the slash */
3603 return pathp; /* no slash, return the entire path */
3606 long smb_ReceiveCoreSearchVolume(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
3608 unsigned char *pathp;
3610 unsigned char mask[11];
3611 unsigned char *statBlockp;
3612 unsigned char initStatBlock[21];
3615 osi_Log0(smb_logp, "SMB receive search volume");
3617 /* pull pathname and stat block out of request */
3618 tp = smb_GetSMBData(inp, NULL);
3619 pathp = smb_ParseASCIIBlock(tp, (char **) &tp);
3620 osi_assert(pathp != NULL);
3621 if (smb_StoreAnsiFilenames)
3622 OemToChar(pathp,pathp);
3623 statBlockp = smb_ParseVblBlock(tp, (char **) &tp, &statLen);
3624 osi_assert(statBlockp != NULL);
3626 statBlockp = initStatBlock;
3630 /* for returning to caller */
3631 smb_Get8Dot3MaskFromPath(mask, pathp);
3633 smb_SetSMBParm(outp, 0, 1); /* we're returning one entry */
3634 tp = smb_GetSMBData(outp, NULL);
3636 *tp++ = 43; /* bytes in a dir entry */
3637 *tp++ = 0; /* high byte in counter */
3639 /* now marshall the dir entry, starting with the search status */
3640 *tp++ = statBlockp[0]; /* Reserved */
3641 memcpy(tp, mask, 11); tp += 11; /* FileName */
3643 /* now pass back server use info, with 1st byte non-zero */
3645 memset(tp, 0, 4); tp += 4; /* reserved for server use */
3647 memcpy(tp, statBlockp+17, 4); tp += 4; /* reserved for consumer */
3649 *tp++ = 0x8; /* attribute: volume */
3659 /* 4 byte file size */
3665 /* finally, null-terminated 8.3 pathname, which we set to AFS */
3666 memset(tp, ' ', 13);
3669 /* set the length of the data part of the packet to 43 + 3, for the dir
3670 * entry plus the 5 and the length fields.
3672 smb_SetSMBDataLength(outp, 46);
3676 long smb_ApplyDirListPatches(smb_dirListPatch_t **dirPatchespp,
3677 cm_user_t *userp, cm_req_t *reqp)
3685 smb_dirListPatch_t *patchp;
3686 smb_dirListPatch_t *npatchp;
3688 for (patchp = *dirPatchespp; patchp; patchp =
3689 (smb_dirListPatch_t *) osi_QNext(&patchp->q)) {
3691 dptr = patchp->dptr;
3693 code = cm_GetSCache(&patchp->fid, &scp, userp, reqp);
3695 if( patchp->flags & SMB_DIRLISTPATCH_DOTFILE )
3696 *dptr++ = SMB_ATTR_HIDDEN;
3699 lock_ObtainMutex(&scp->mx);
3700 code = cm_SyncOp(scp, NULL, userp, reqp, 0,
3701 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3703 lock_ReleaseMutex(&scp->mx);
3704 cm_ReleaseSCache(scp);
3705 if (patchp->flags & SMB_DIRLISTPATCH_DOTFILE)
3706 *dptr++ = SMB_ATTR_HIDDEN;
3710 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3712 attr = smb_Attributes(scp);
3713 /* check hidden attribute (the flag is only ON when dot file hiding is on ) */
3714 if (patchp->flags & SMB_DIRLISTPATCH_DOTFILE)
3715 attr |= SMB_ATTR_HIDDEN;
3719 smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime);
3722 shortTemp = (unsigned short) (dosTime & 0xffff);
3723 *((u_short *)dptr) = shortTemp;
3726 /* and copy out date */
3727 shortTemp = (unsigned short) ((dosTime>>16) & 0xffff);
3728 *((u_short *)dptr) = shortTemp;
3731 /* copy out file length */
3732 *((u_long *)dptr) = scp->length.LowPart;
3734 lock_ReleaseMutex(&scp->mx);