From 6e06e55f04c4806f3132f1b09c889e332c4c8e97 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Tue, 19 Apr 2005 06:11:17 +0000 Subject: [PATCH] STABLE14-windows-misc-20050418 Support for WinLogon "logon" event handler to allow use in multi-domain forests with a cross-realm trust between a MIT realm and a root domain with workstations in a sub-domain. Add support for rx_StartClientThread Prepare for allowing maxVolumes and maxCells to be configurable via the registry. --- src/WINNT/afsd/afskfw.c | 46 +++++++++++++++++ src/WINNT/afsd/afskfw.h | 1 + src/WINNT/afsd/afslogon.c | 98 +++++++++++++++++++++++++++++++++--- src/WINNT/afsd/cm_aclent.c | 36 ++++++++----- src/WINNT/afsd/cm_daemon.c | 2 + src/WINNT/afsd/cm_memmap.c | 20 +++++--- src/WINNT/afsd/cm_vnodeops.c | 23 ++++----- src/WINNT/afsd/smb.c | 2 + src/WINNT/afsd/smb.h | 6 +++ src/WINNT/afsd/smb3.c | 4 +- 10 files changed, 196 insertions(+), 42 deletions(-) diff --git a/src/WINNT/afsd/afskfw.c b/src/WINNT/afsd/afskfw.c index a1fc846c3..adc858705 100644 --- a/src/WINNT/afsd/afskfw.c +++ b/src/WINNT/afsd/afskfw.c @@ -3409,3 +3409,49 @@ BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig) return serverReachable; } +BOOL +KFW_AFS_get_lsa_principal(char * szUser, DWORD *dwSize) +{ + krb5_context ctx = 0; + krb5_error_code code; + krb5_ccache mslsa_ccache=0; + krb5_principal princ = 0; + char * pname = 0; + BOOL success = 0; + + if (!KFW_is_available()) + return FALSE; + + if (code = pkrb5_init_context(&ctx)) + goto cleanup; + + if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache)) + goto cleanup; + + if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ)) + goto cleanup; + + if (code = pkrb5_unparse_name(ctx, princ, &pname)) + goto cleanup; + + if ( strlen(pname) < *dwSize ) { + strncpy(szUser, pname, *dwSize); + szUser[*dwSize-1] = '\0'; + success = 1; + } + *dwSize = strlen(pname); + + cleanup: + if (pname) + pkrb5_free_unparsed_name(ctx, pname); + + if (princ) + pkrb5_free_principal(ctx, princ); + + if (mslsa_ccache) + pkrb5_cc_close(ctx, mslsa_ccache); + + if (ctx) + pkrb5_free_context(ctx); + return success; +} \ No newline at end of file diff --git a/src/WINNT/afsd/afskfw.h b/src/WINNT/afsd/afskfw.h index 995d038fb..352e0595a 100644 --- a/src/WINNT/afsd/afskfw.h +++ b/src/WINNT/afsd/afskfw.h @@ -60,6 +60,7 @@ BOOL KFW_AFS_wait_for_service_start(void); BOOL KFW_probe_kdc(struct afsconf_cell *); int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *); void KFW_import_windows_lsa(void); +BOOL KFW_AFS_get_lsa_principal(char *, DWORD *); /* From afs/krb_prot.h */ /* values for kerb error codes */ diff --git a/src/WINNT/afsd/afslogon.c b/src/WINNT/afsd/afslogon.c index 0e9788ee2..34833aa80 100644 --- a/src/WINNT/afsd/afslogon.c +++ b/src/WINNT/afsd/afslogon.c @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -26,6 +27,7 @@ #include "cm_config.h" #include "krb.h" #include "afskfw.h" +#include "lanahelper.h" #include @@ -561,8 +563,6 @@ GetDomainLogonOptions( PLUID lpLogonId, char * username, char * domain, LogonOpt } if (hkTemp) { - HRESULT hr; - size_t len; CHAR * thesecells; /* dwSize still has the size of the required buffer in bytes. */ @@ -988,12 +988,11 @@ VOID AFS_Logoff_Event( PWLX_NOTIFICATION_INFO pInfo ) DWORD len = 1024; PTOKEN_USER tokenUser = NULL; DWORD retLen; - HANDLE hToken; /* Make sure the AFS Libraries are initialized */ AfsLogonInit(); - DebugEvent0("AFS_Logoff_Event - Starting"); + DebugEvent0("AFS_Logoff_Event - Start"); if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen)) { @@ -1002,7 +1001,7 @@ VOID AFS_Logoff_Event( PWLX_NOTIFICATION_INFO pInfo ) if (!GetTokenInformation(pInfo->hToken, TokenUser, tokenUser, retLen, &retLen)) { - DebugEvent("GetTokenInformation failed: GLE = %lX", GetLastError()); + DebugEvent("AFS_Logoff_Event - GetTokenInformation failed: GLE = %lX", GetLastError()); } } } @@ -1020,7 +1019,7 @@ VOID AFS_Logoff_Event( PWLX_NOTIFICATION_INFO pInfo ) } if (strlen(profileDir)) { - DebugEvent("Profile Directory: %s", profileDir); + DebugEvent("AFS_Logoff_Event - Profile Directory: %s", profileDir); if (!IsPathInAfs(profileDir)) { if (code = ktc_ForgetAllTokens()) DebugEvent("AFS_Logoff_Event - ForgetAllTokens failed [%lX]",code); @@ -1035,5 +1034,92 @@ VOID AFS_Logoff_Event( PWLX_NOTIFICATION_INFO pInfo ) if ( tokenUser ) LocalFree(tokenUser); + + DebugEvent0("AFS_Logoff_Event - End"); } +VOID AFS_Logon_Event( PWLX_NOTIFICATION_INFO pInfo ) +{ + DWORD code; + TCHAR profileDir[1024] = TEXT(""); + DWORD len = 1024; + PTOKEN_USER tokenUser = NULL; + DWORD retLen; + HANDLE hToken; + + WCHAR szUserW[128] = L""; + char szUserA[128] = ""; + char szClient[MAX_PATH]; + char szPath[MAX_PATH] = ""; + NETRESOURCE nr; + DWORD res; + DWORD gle; + DWORD dwSize; + + /* Make sure the AFS Libraries are initialized */ + AfsLogonInit(); + + DebugEvent0("AFS_Logon_Event - Start"); + + if (!GetTokenInformation(pInfo->hToken, TokenUser, NULL, 0, &retLen)) + { + if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) { + tokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen); + + if (!GetTokenInformation(pInfo->hToken, TokenUser, tokenUser, retLen, &retLen)) + { + DebugEvent("AFS_Logon_Event - GetTokenInformation failed: GLE = %lX", GetLastError()); + } + } + } + + /* We can't use pInfo->Domain for the domain since in the cross realm case + * this is source domain and not the destination domain. + */ + if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, pInfo->Domain)) { + WCHAR Domain[64]=L""; + GetLocalShortDomain(Domain, sizeof(Domain)); + if (QueryAdHomePathFromSid( profileDir, sizeof(profileDir), tokenUser->User.Sid, Domain)) { + if (NetUserGetProfilePath(pInfo->Domain, pInfo->UserName, profileDir, len)) + GetUserProfileDirectory(pInfo->hToken, profileDir, &len); + } + } + + if (strlen(profileDir)) { + DebugEvent("AFS_Logon_Event - Profile Directory: %s", profileDir); + } else { + DebugEvent0("AFS_Logon_Event - Unable to load profile"); + } + + dwSize = sizeof(szUserA); + if (!KFW_AFS_get_lsa_principal(szUserA, &dwSize)) { + StringCbPrintfW(szUserW, sizeof(szUserW), L"%s\\%s", pInfo->Domain, pInfo->UserName); + WideCharToMultiByte(CP_ACP, 0, szUserW, -1, szUserA, MAX_PATH, NULL, NULL); + } + + if (szUserA[0]) + { + lana_GetNetbiosName(szClient, LANA_NETBIOS_NAME_FULL); + StringCbPrintf(szPath, sizeof(szPath), "\\\\%s", szClient); + + DebugEvent("AFS_Logon_Event - Logon Name: %s", szUserA); + + memset (&nr, 0x00, sizeof(NETRESOURCE)); + nr.dwType=RESOURCETYPE_DISK; + nr.lpLocalName=0; + nr.lpRemoteName=szPath; + res = WNetAddConnection2(&nr,NULL,szUserA,0); + if (res) + DebugEvent("AFS_Logon_Event - WNetAddConnection2(%s,%s) failed: 0x%X", + szPath, szUserA,res); + else + DebugEvent0("AFS_Logon_Event - WNetAddConnection2() succeeded"); + } else + DebugEvent("AFS_Logon_Event - User name conversion failed: GLE = 0x%X",GetLastError()); + + if ( tokenUser ) + LocalFree(tokenUser); + + DebugEvent0("AFS_Logon_Event - End"); +} + diff --git a/src/WINNT/afsd/cm_aclent.c b/src/WINNT/afsd/cm_aclent.c index b0f9a6dc6..52e635e64 100644 --- a/src/WINNT/afsd/cm_aclent.c +++ b/src/WINNT/afsd/cm_aclent.c @@ -37,17 +37,20 @@ static void CleanupACLEnt(cm_aclent_t * aclp) cm_aclent_t **laclpp; if (aclp->backp) { - /* - * Remove the entry from the vnode's list - */ - laclpp = &aclp->backp->randomACLp; - for (taclp = *laclpp; taclp; laclpp = &taclp->nextp, taclp = *laclpp) { - if (taclp == aclp) - break; + if (aclp->backp->randomACLp) { + /* + * Remove the entry from the vnode's list + */ + lock_AssertMutex(&aclp->backp->mx); + laclpp = &aclp->backp->randomACLp; + for (taclp = *laclpp; taclp; laclpp = &taclp->nextp, taclp = *laclpp) { + if (taclp == aclp) + break; + } + if (!taclp) + osi_panic("CleanupACLEnt race", __FILE__, __LINE__); + *laclpp = aclp->nextp; /* remove from vnode list */ } - if (!taclp) - osi_panic("CleanupACLEnt race", __FILE__, __LINE__); - *laclpp = aclp->nextp; /* remove from vnode list */ aclp->backp = NULL; } @@ -110,10 +113,11 @@ long cm_FindACLCache(cm_scache_t *scp, cm_user_t *userp, long *rightsp) * This function returns a free (not in the LRU queue) acl cache entry. * It must be called with the cm_aclLock lock held */ -static cm_aclent_t *GetFreeACLEnt(void) +static cm_aclent_t *GetFreeACLEnt(cm_scache_t * scp) { cm_aclent_t *aclp; - + cm_scache_t *ascp = 0; + if (cm_data.aclLRUp == NULL) osi_panic("empty aclent LRU", __FILE__, __LINE__); @@ -121,8 +125,14 @@ static cm_aclent_t *GetFreeACLEnt(void) cm_data.aclLRUEndp = (cm_aclent_t *) osi_QPrev(&aclp->q); osi_QRemove((osi_queue_t **) &cm_data.aclLRUp, &aclp->q); + if (aclp->backp && scp != aclp->backp) { + ascp = aclp->backp; + lock_ObtainMutex(&ascp->mx); + } CleanupACLEnt(aclp); + if (ascp) + lock_ReleaseMutex(&ascp->mx); return aclp; } @@ -153,7 +163,7 @@ long cm_AddACLCache(cm_scache_t *scp, cm_user_t *userp, long rights) * and reuse. But first try the free list and see if there's already * someone there. */ - aclp = GetFreeACLEnt(); /* can't fail, panics instead */ + aclp = GetFreeACLEnt(scp); /* can't fail, panics instead */ osi_QAddH((osi_queue_t **) &cm_data.aclLRUp, (osi_queue_t **) &cm_data.aclLRUEndp, &aclp->q); aclp->backp = scp; aclp->nextp = scp->randomACLp; diff --git a/src/WINNT/afsd/cm_daemon.c b/src/WINNT/afsd/cm_daemon.c index 5a0106dcd..81ba1459c 100644 --- a/src/WINNT/afsd/cm_daemon.c +++ b/src/WINNT/afsd/cm_daemon.c @@ -42,6 +42,8 @@ void cm_BkgDaemon(long parm) { cm_bkgRequest_t *rp; + rx_StartClientThread(); + lock_ObtainWrite(&cm_daemonLock); while (daemon_ShutdownFlag == 0) { if (!cm_bkgListEndp) { diff --git a/src/WINNT/afsd/cm_memmap.c b/src/WINNT/afsd/cm_memmap.c index 89b387b9f..8f63d7e0f 100644 --- a/src/WINNT/afsd/cm_memmap.c +++ b/src/WINNT/afsd/cm_memmap.c @@ -102,13 +102,13 @@ ComputeSizeOfDataHeaders(DWORD cacheBlocks) } DWORD -ComputeSizeOfMappingFile(DWORD stats, DWORD chunkSize, DWORD cacheBlocks, DWORD blockSize) +ComputeSizeOfMappingFile(DWORD stats, DWORD maxVols, DWORD maxCells, DWORD chunkSize, DWORD cacheBlocks, DWORD blockSize) { DWORD size; size = ComputeSizeOfConfigData() - + ComputeSizeOfVolumes(stats/2) - + ComputeSizeOfCells(stats/4) + + ComputeSizeOfVolumes(maxVols) + + ComputeSizeOfCells(maxCells) + ComputeSizeOfACLCache(stats) + ComputeSizeOfSCache(stats) + ComputeSizeOfSCacheHT(stats) @@ -417,11 +417,13 @@ cm_InitMappedMemory(DWORD virtualCache, char * cachePath, DWORD stats, DWORD chu PSECURITY_ATTRIBUTES psa; int newFile = 1; DWORD mappingSize; + DWORD maxVols = stats/2; + DWORD maxCells = stats/4; char * baseAddress = NULL; cm_config_data_t * config_data_p; char * p; - mappingSize = ComputeSizeOfMappingFile(stats, chunkSize, cacheBlocks, CM_CONFIGDEFAULT_BLOCKSIZE); + mappingSize = ComputeSizeOfMappingFile(stats, maxVols, maxCells, chunkSize, cacheBlocks, CM_CONFIGDEFAULT_BLOCKSIZE); if ( !virtualCache ) { psa = CreateCacheFileSA(); @@ -529,6 +531,8 @@ cm_InitMappedMemory(DWORD virtualCache, char * cachePath, DWORD stats, DWORD chu if ( config_data_p->size == sizeof(cm_config_data_t) && config_data_p->magic == CM_CONFIG_DATA_MAGIC && config_data_p->stats == stats && + config_data_p->maxVolumes == maxVols && + config_data_p->maxCells == maxCells && config_data_p->chunkSize == chunkSize && config_data_p->buf_nbuffers == cacheBlocks && config_data_p->blockSize == CM_CONFIGDEFAULT_BLOCKSIZE && @@ -622,9 +626,9 @@ cm_InitMappedMemory(DWORD virtualCache, char * cachePath, DWORD stats, DWORD chu baseAddress += ComputeSizeOfConfigData(); cm_data.volumeBaseAddress = (cm_volume_t *) baseAddress; - baseAddress += ComputeSizeOfVolumes(stats/2); + baseAddress += ComputeSizeOfVolumes(maxVols); cm_data.cellBaseAddress = (cm_cell_t *) baseAddress; - baseAddress += ComputeSizeOfCells(stats/4); + baseAddress += ComputeSizeOfCells(maxCells); cm_data.aclBaseAddress = (cm_aclent_t *) baseAddress; baseAddress += ComputeSizeOfACLCache(stats); cm_data.scacheBaseAddress = (cm_scache_t *) baseAddress; @@ -653,10 +657,10 @@ cm_InitMappedMemory(DWORD virtualCache, char * cachePath, DWORD stats, DWORD chu RpcStringFree(&p); afsi_log("Initializing Volume Data"); - cm_InitVolume(newFile, stats/2); + cm_InitVolume(newFile, maxVols); afsi_log("Initializing Cell Data"); - cm_InitCell(newFile, stats/4); + cm_InitCell(newFile, maxCells); afsi_log("Initializing ACL Data"); cm_InitACLCache(newFile, 2*stats); diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index 7cdecdc7b..20872df2b 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -2692,7 +2692,7 @@ long cm_Lock(cm_scache_t *scp, unsigned char LockType, void **lockpp) { long code; - int Which = ((LockType & 0x1) ? LockRead : LockWrite); + int Which = ((LockType & LOCKING_ANDX_SHARED_LOCK) ? LockRead : LockWrite); AFSFid tfid; AFSVolSync volSync; cm_conn_t *connp; @@ -2706,13 +2706,10 @@ long cm_Lock(cm_scache_t *scp, unsigned char LockType, */ q = scp->fileLocks; while (q) { - fileLock = (cm_file_lock_t *) - ((char *) q - offsetof(cm_file_lock_t, fileq)); - if ((fileLock->flags & - (CM_FILELOCK_FLAG_INVALID | CM_FILELOCK_FLAG_WAITING)) - == 0) { - if ((LockType & 0x1) == 0 - || (fileLock->LockType & 0x1) == 0) + fileLock = (cm_file_lock_t *)((char *) q - offsetof(cm_file_lock_t, fileq)); + if ((fileLock->flags & (CM_FILELOCK_FLAG_INVALID | CM_FILELOCK_FLAG_WAITING)) == 0) { + if ((LockType & LOCKING_ANDX_SHARED_LOCK) == 0 || + (fileLock->LockType & LOCKING_ANDX_SHARED_LOCK) == 0) return CM_ERROR_WOULDBLOCK; found = 1; } @@ -2766,7 +2763,7 @@ long cm_Unlock(cm_scache_t *scp, unsigned char LockType, cm_user_t *userp, cm_req_t *reqp) { long code = 0; - int Which = ((LockType & 0x1) ? LockRead : LockWrite); + int Which = ((LockType & LOCKING_ANDX_SHARED_LOCK) ? LockRead : LockWrite); AFSFid tfid; AFSVolSync volSync; cm_conn_t *connp; @@ -2795,7 +2792,7 @@ long cm_Unlock(cm_scache_t *scp, unsigned char LockType, ourLock = fileLock; qq = q; } - else if (fileLock->LockType & 0x1) + else if (fileLock->LockType & LOCKING_ANDX_SHARED_LOCK) anotherReader = 1; q = osi_QNext(q); } @@ -2907,7 +2904,7 @@ void cm_CheckLocks() long cm_RetryLock(cm_file_lock_t *oldFileLock, int vcp_is_dead) { long code; - int Which = ((oldFileLock->LockType & 0x1) ? LockRead : LockWrite); + int Which = ((oldFileLock->LockType & LOCKING_ANDX_SHARED_LOCK) ? LockRead : LockWrite); cm_scache_t *scp; AFSFid tfid; AFSVolSync volSync; @@ -2939,8 +2936,8 @@ long cm_RetryLock(cm_file_lock_t *oldFileLock, int vcp_is_dead) if ((fileLock->flags & (CM_FILELOCK_FLAG_INVALID | CM_FILELOCK_FLAG_WAITING)) == 0) { - if ((oldFileLock->LockType & 0x1) == 0 - || (fileLock->LockType & 0x1) == 0) { + if ((oldFileLock->LockType & LOCKING_ANDX_SHARED_LOCK) == 0 + || (fileLock->LockType & LOCKING_ANDX_SHARED_LOCK) == 0) { cm_ReleaseSCache(scp); return CM_ERROR_WOULDBLOCK; } diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index df404130f..f7f7c5e98 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -6956,6 +6956,8 @@ void smb_Server(VOID *parmp) dos_ptr dos_ncb; #endif /* DJGPP */ + rx_StartClientThread(); + outncbp = GetNCB(); outbufp = GetPacket(); outbufp->ncbp = outncbp; diff --git a/src/WINNT/afsd/smb.h b/src/WINNT/afsd/smb.h index 78a145d4f..4a8e3cca0 100644 --- a/src/WINNT/afsd/smb.h +++ b/src/WINNT/afsd/smb.h @@ -365,6 +365,12 @@ typedef struct smb_fid { #define SMB_ATTR_NOT_CONTENT_INDEXED 0x2000 #define SMB_ATTR_ENCRYPTED 0x4000 +#define LOCKING_ANDX_SHARED_LOCK 0x01 /* Read-only lock */ +#define LOCKING_ANDX_OPLOCK_RELEASE 0x02 /* Oplock break notification */ +#define LOCKING_ANDX_CHANGE_LOCKTYPE 0x04 /* Change lock type */ +#define LOCKING_ANDX_CANCEL_LOCK 0x08 /* Cancel outstanding request */ +#define LOCKING_ANDX_LARGE_FILES 0x10 /* Large file locking format */ + /* for tracking in-progress directory searches */ typedef struct smb_dirSearch { osi_queue_t q; /* queue of all outstanding cookies */ diff --git a/src/WINNT/afsd/smb3.c b/src/WINNT/afsd/smb3.c index 13989b490..cbdf54fe4 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -4832,7 +4832,7 @@ long smb_ReceiveV3LockingX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) op = smb_GetSMBData(inp, NULL); for (i=0; i