/***************************************************************************** * WCMD_getfileowner * * Reverse a WCHARacter string in-place (strrev() is not available under unixen :-( ). */ static void WCMD_getfileowner(WCHAR *filename, WCHAR *owner, int ownerlen) { ULONG sizeNeeded = 0; DWORD rc; WCHAR name[MAXSTRING]; WCHAR domain[MAXSTRING]; /* In case of error, return empty string */ *owner = 0x00; /* Find out how much space we need for the owner security descriptor */ GetFileSecurityW(filename, OWNER_SECURITY_INFORMATION, 0, 0, &sizeNeeded); rc = GetLastError(); if(rc == ERROR_INSUFFICIENT_BUFFER && sizeNeeded > 0) { LPBYTE secBuffer; PSID pSID = NULL; BOOL defaulted = FALSE; ULONG nameLen = MAXSTRING; ULONG domainLen = MAXSTRING; SID_NAME_USE nameuse; secBuffer = HeapAlloc(GetProcessHeap(),0,sizeNeeded * sizeof(BYTE)); if(!secBuffer) return; /* Get the owners security descriptor */ if(!GetFileSecurityW(filename, OWNER_SECURITY_INFORMATION, secBuffer, sizeNeeded, &sizeNeeded)) { HeapFree(GetProcessHeap(),0,secBuffer); return; } /* Get the SID from the SD */ if(!GetSecurityDescriptorOwner(secBuffer, &pSID, &defaulted)) { HeapFree(GetProcessHeap(),0,secBuffer); return; } /* Convert to a username */ if (LookupAccountSidW(NULL, pSID, name, &nameLen, domain, &domainLen, &nameuse)) { static const WCHAR fmt[] = {'%','s','%','c','%','s','\0'}; snprintfW(owner, ownerlen, fmt, domain, '\\', name); } HeapFree(GetProcessHeap(),0,secBuffer); } return; }
/************************************************************************** * RetreiveFileSecurity [SETUPAPI.@] * * Retrieve the security descriptor that is associated with the given file. * * PARAMS * lpFileName [I] Name of the file * * RETURNS * Success: ERROR_SUCCESS * Failure: other */ DWORD WINAPI RetreiveFileSecurity(LPCWSTR lpFileName, PSECURITY_DESCRIPTOR *pSecurityDescriptor) { PSECURITY_DESCRIPTOR SecDesc; DWORD dwSize = 0x100; DWORD dwError; TRACE("%s %p\n", debugstr_w(lpFileName), pSecurityDescriptor); SecDesc = MyMalloc(dwSize); if (SecDesc == NULL) return ERROR_NOT_ENOUGH_MEMORY; if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, SecDesc, dwSize, &dwSize)) { *pSecurityDescriptor = SecDesc; return ERROR_SUCCESS; } dwError = GetLastError(); if (dwError != ERROR_INSUFFICIENT_BUFFER) { MyFree(SecDesc); return dwError; } SecDesc = MyRealloc(SecDesc, dwSize); if (SecDesc == NULL) return ERROR_NOT_ENOUGH_MEMORY; if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, SecDesc, dwSize, &dwSize)) { *pSecurityDescriptor = SecDesc; return ERROR_SUCCESS; } dwError = GetLastError(); MyFree(SecDesc); return dwError; }
int winAccessW(const wchar_t *path, int mode) { DWORD attr = GetFileAttributesW(path); if(attr == 0xffffffff) return -1; if(mode == F_OK) return 0; if(mode & X_OK) if(!(attr & FILE_ATTRIBUTE_DIRECTORY)) { /* Directory, so OK */ /* Look at extension for executables */ wchar_t *p = wcsrchr(path, '.'); if(p == NULL || !((wcsicmp(p, L".exe") == 0) || (wcsicmp(p, L".com") == 0) || (wcsicmp(p, L".bat") == 0) || (wcsicmp(p, L".cmd") == 0)) ) return -1; } { /* Now look for file security info */ SECURITY_DESCRIPTOR *sdPtr = NULL; DWORD size = 0; GENERIC_MAPPING genMap; HANDLE hToken = NULL; DWORD desiredAccess = 0; DWORD grantedAccess = 0; BOOL accessYesNo = FALSE; PRIVILEGE_SET privSet; DWORD privSetSize = sizeof(PRIVILEGE_SET); int error; /* get size */ GetFileSecurityW(path, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, 0, 0, &size); error = GetLastError(); if (error != ERROR_INSUFFICIENT_BUFFER) return -1; sdPtr = (SECURITY_DESCRIPTOR *) alloca(size); if(!GetFileSecurityW(path, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, sdPtr, size, &size)) return -1; /* * Perform security impersonation of the user and open the * resulting thread token. */ if(!ImpersonateSelf(SecurityImpersonation)) return -1; if(!OpenThreadToken(GetCurrentThread (), TOKEN_DUPLICATE | TOKEN_QUERY, FALSE, &hToken)) return -1; if (mode & R_OK) desiredAccess |= FILE_GENERIC_READ; if (mode & W_OK) desiredAccess |= FILE_GENERIC_WRITE; if (mode & X_OK) desiredAccess |= FILE_GENERIC_EXECUTE; memset(&genMap, 0x0, sizeof (GENERIC_MAPPING)); genMap.GenericRead = FILE_GENERIC_READ; genMap.GenericWrite = FILE_GENERIC_WRITE; genMap.GenericExecute = FILE_GENERIC_EXECUTE; genMap.GenericAll = FILE_ALL_ACCESS; if(!AccessCheck(sdPtr, hToken, desiredAccess, &genMap, &privSet, &privSetSize, &grantedAccess, &accessYesNo)) { CloseHandle(hToken); return -1; } CloseHandle(hToken); if (!accessYesNo) return -1; if ((mode & W_OK) && !(attr & FILE_ATTRIBUTE_DIRECTORY) && (attr & FILE_ATTRIBUTE_READONLY)) return -1; } return 0; }
JNIEXPORT void JNICALL Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_copyPermissionW( JNIEnv *env, jclass cla, jstring _fileNameIn, jstring _fileNameOut ) { WCHAR file_name_in[2048]; WCHAR file_name_out[2048]; if ( !jstringToCharsW( env, _fileNameIn, file_name_in, sizeof( file_name_in )-1)){ return; } if ( !jstringToCharsW( env, _fileNameOut, file_name_out, sizeof( file_name_out )-1)){ return; } SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION; DWORD cbFileSD = 0; PSECURITY_DESCRIPTOR pFileSD = NULL; BOOL ok = GetFileSecurityW(file_name_in, secInfo, pFileSD, 0, &cbFileSD); // API should have failed with insufficient buffer. if ( ok ){ throwException( env, "copyPermission", "GetFileSecurity ok" ); return; }else if (GetLastError() == ERROR_FILE_NOT_FOUND) { throwException( env, "copyPermission", "from file not found" ); return; }else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { throwException( env, "copyPermission", "GetFileSecurity unexpected response", GetLastError() ); return; }else{ pFileSD = myheapalloc( cbFileSD ); if (!pFileSD) { throwException( env, "copyPermission", "no memory" ); return; } ok = GetFileSecurityW(file_name_in, secInfo, pFileSD, cbFileSD, &cbFileSD ); if (!ok) { myheapfree( pFileSD ); throwException( env, "copyPermission", "GetFileSecurity", GetLastError()); return; } ok = SetFileSecurityW( file_name_out, secInfo, pFileSD ); myheapfree( pFileSD ); if ( !ok ){ if (GetLastError() == ERROR_FILE_NOT_FOUND) { throwException( env, "copyPermission", "to file not found" ); }else{ throwException( env, "copyPermission", "SetFileSecurity unexpected response", GetLastError() ); } } } }
/* return TRUE on a successful copy; otherwise, FALSE. */ BOOL GetFileSecurityAttributes ( PCWSTR w_source, PSECURITY_ATTRIBUTES *security_attributes ) { PSECURITY_ATTRIBUTES destination_attributes = NULL; PSECURITY_DESCRIPTOR source_descriptor = NULL; PBYTE buffer = NULL; DWORD size = 0, extra = condor_roundup ( sizeof ( PSECURITY_DESCRIPTOR ) ), last_error = ERROR_SUCCESS; BOOL have_security_info = FALSE, ok = FALSE; __try { /* first, determine the required buffer size */ have_security_info = GetFileSecurityW ( w_source, SACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, NULL, 0, &size ); if ( !have_security_info ) { last_error = GetLastError (); __leave; } /* try and allocated the required buffer size, plus some wiggle room */ buffer = new BYTE[size + extra]; if ( !buffer ) { last_error = GetLastError (); __leave; } /* translate the buffer into the structure we want */ destination_attributes = (PSECURITY_ATTRIBUTES) buffer; /* to simplify deletion, we've allocated everything as one big block: placing the descriptor at the end of the attributes structure. this means we only need to call delete [] once on the returned pointer */ source_descriptor = (PSECURITY_DESCRIPTOR) ( ( (ULONG) buffer ) + extra ); destination_attributes->lpSecurityDescriptor = source_descriptor; /* now, with the buffers allocated, get the actual information we are interested in */ have_security_info = GetFileSecurityW ( w_source, SACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, source_descriptor, size, &size ); if ( !have_security_info ) { last_error = GetLastError (); __leave; } /* fill out the remaining parts of the security attributes structure */ destination_attributes->nLength = sizeof ( PSECURITY_ATTRIBUTES ); destination_attributes->bInheritHandle = FALSE; /* we made it! */ ok = TRUE; } __finally { /* propagate the last error */ SetLastError ( ok ? ERROR_SUCCESS : last_error ); if ( !ok ) { *security_attributes = NULL; delete [] buffer; buffer = NULL; } *security_attributes = destination_attributes; } return ok; }
/* ** Wrapper around the access() system call. This code was copied from Tcl ** 8.6 and then modified. */ int win32_access(const char *zFilename, int flags){ int rc = 0; PSECURITY_DESCRIPTOR pSd = NULL; unsigned long size; PSID pSid = NULL; BOOL sidDefaulted; BOOL impersonated = FALSE; SID_IDENTIFIER_AUTHORITY unmapped = {{0, 0, 0, 0, 0, 22}}; GENERIC_MAPPING genMap; HANDLE hToken = NULL; DWORD desiredAccess = 0, grantedAccess = 0; BOOL accessYesNo = FALSE; PRIVILEGE_SET privSet; DWORD privSetSize = sizeof(PRIVILEGE_SET); wchar_t *zMbcs = fossil_utf8_to_filename(zFilename); DWORD attr = GetFileAttributesW(zMbcs); if( attr==INVALID_FILE_ATTRIBUTES ){ /* * File might not exist. */ if( GetLastError()!=ERROR_SHARING_VIOLATION ){ rc = -1; goto done; } } if( flags==F_OK ){ /* * File exists, nothing else to check. */ goto done; } if( (flags & W_OK) && (attr & FILE_ATTRIBUTE_READONLY) && !(attr & FILE_ATTRIBUTE_DIRECTORY) ){ /* * The attributes say the file is not writable. If the file is a * regular file (i.e., not a directory), then the file is not * writable, full stop. For directories, the read-only bit is * (mostly) ignored by Windows, so we can't ascertain anything about * directory access from the attrib data. */ rc = -1; goto done; } /* * It looks as if the permissions are ok, but if we are on NT, 2000 or XP, * we have a more complex permissions structure so we try to check that. * The code below is remarkably complex for such a simple thing as finding * what permissions the OS has set for a file. */ /* * First find out how big the buffer needs to be. */ size = 0; GetFileSecurityW(zMbcs, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION, 0, 0, &size); /* * Should have failed with ERROR_INSUFFICIENT_BUFFER */ if( GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){ /* * Most likely case is ERROR_ACCESS_DENIED, which we will convert to * EACCES - just what we want! */ rc = -1; goto done; } /* * Now size contains the size of buffer needed. */ pSd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(), 0, size); if( pSd==NULL ){ rc = -1; goto done; } /* * Call GetFileSecurity() for real. */ if( !GetFileSecurityW(zMbcs, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION, pSd, size, &size) ){ /* * Error getting owner SD */ rc = -1; goto done; } /* * As of Samba 3.0.23 (10-Jul-2006), unmapped users and groups are * assigned to SID domains S-1-22-1 and S-1-22-2, where "22" is the * top-level authority. If the file owner and group is unmapped then * the ACL access check below will only test against world access, * which is likely to be more restrictive than the actual access * restrictions. Since the ACL tests are more likely wrong than * right, skip them. Moreover, the unix owner access permissions are * usually mapped to the Windows attributes, so if the user is the * file owner then the attrib checks above are correct (as far as they * go). */ if( !GetSecurityDescriptorOwner(pSd, &pSid, &sidDefaulted) || memcmp(GetSidIdentifierAuthority(pSid), &unmapped, sizeof(SID_IDENTIFIER_AUTHORITY))==0 ){ goto done; /* Attrib tests say access allowed. */ } /* * Perform security impersonation of the user and open the resulting * thread token. */ if( !ImpersonateSelf(SecurityImpersonation) ){ /* * Unable to perform security impersonation. */ rc = -1; goto done; } impersonated = TRUE; if( !OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE | TOKEN_QUERY, FALSE, &hToken) ){ /* * Unable to get current thread's token. */ rc = -1; goto done; } /* * Setup desiredAccess according to the access priveleges we are * checking. */ if( flags & R_OK ){ desiredAccess |= FILE_GENERIC_READ; } if( flags & W_OK){ desiredAccess |= FILE_GENERIC_WRITE; } memset(&genMap, 0, sizeof(GENERIC_MAPPING)); genMap.GenericRead = FILE_GENERIC_READ; genMap.GenericWrite = FILE_GENERIC_WRITE; genMap.GenericExecute = FILE_GENERIC_EXECUTE; genMap.GenericAll = FILE_ALL_ACCESS; /* * Perform access check using the token. */ if( !AccessCheck(pSd, hToken, desiredAccess, &genMap, &privSet, &privSetSize, &grantedAccess, &accessYesNo) ){ /* * Unable to perform access check. */ rc = -1; goto done; } if( !accessYesNo ) rc = -1; done: if( hToken != NULL ){ CloseHandle(hToken); } if( impersonated ){ RevertToSelf(); impersonated = FALSE; } if( pSd!=NULL ){ HeapFree(GetProcessHeap(), 0, pSd); } fossil_filename_free(zMbcs); return rc; }
void ServiceStart(BOOL aService) { DWORD ThreadID,i; wchar_t filename[MAX_PATH],access_filename[MAX_PATH]; InitInfo(); InitNotify(); { HANDLE token; PTOKEN_USER token_user=NULL; SID_IDENTIFIER_AUTHORITY SIDAuthSystem={SECURITY_NT_AUTHORITY}; PSID pSystemSid=NULL; if(AllocateAndInitializeSid(&SIDAuthSystem,1,SECURITY_LOCAL_SYSTEM_RID,0,0,0,0,0,0,0,&pSystemSid)) { if(OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY,&token)) { token_user=(PTOKEN_USER)DefaultTokenInformation(token,TokenUser); if(token_user) { if((token_user->User.Sid)&&(pSystemSid)&&(IsValidSid(token_user->User.Sid))&&(IsValidSid(pSystemSid))&&(EqualSid(token_user->User.Sid,pSystemSid))) IsSystem=TRUE; free(token_user); } CloseHandle(token); } FreeSid(pSystemSid); } } //get security from file. EnablePrivilege(L"SeSecurityPrivilege"); if(!pipe_sd&&GetModuleFileNameW(NULL,filename,sizeofa(filename))) { wchar_t *filename_ptr; DWORD res=GetFullPathNameW(filename,sizeofa(access_filename),access_filename,&filename_ptr); if(res&&(res<sizeofa(access_filename))&&filename_ptr) { DWORD needed; wcscpy(filename_ptr,ACCESS_NAMEW); if(!GetFileSecurityW(access_filename,DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION,NULL,0,&needed)) if(GetLastError()==ERROR_INSUFFICIENT_BUFFER) { pipe_sd=(PSECURITY_DESCRIPTOR)malloc(needed); if(pipe_sd) { if(!GetFileSecurityW(access_filename,DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION,pipe_sd,needed,&needed)) { free(pipe_sd); pipe_sd=NULL; } } } } } //create default security if(!pipe_sd) { PSID pAccessSid=NULL; PSID pSystemSid=NULL; SID_IDENTIFIER_AUTHORITY SIDAuthLocal={SECURITY_LOCAL_SID_AUTHORITY}; SID_IDENTIFIER_AUTHORITY SIDAuthEveryone={SECURITY_WORLD_SID_AUTHORITY}; SID_IDENTIFIER_AUTHORITY SIDAuthSystem={SECURITY_NT_AUTHORITY}; DWORD sd_size=SECURITY_DESCRIPTOR_MIN_LENGTH+sizeof(ACL); PACL pAcl=NULL; if(GetAllowNetwork()?AllocateAndInitializeSid(&SIDAuthEveryone,1,SECURITY_WORLD_RID,0,0,0,0,0,0,0,&pAccessSid):AllocateAndInitializeSid(&SIDAuthLocal,1,SECURITY_LOCAL_RID,0,0,0,0,0,0,0,&pAccessSid)) { if(AllocateAndInitializeSid(&SIDAuthSystem,1,SECURITY_LOCAL_SYSTEM_RID,0,0,0,0,0,0,0,&pSystemSid)) { sd_size+=2*(sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD))+GetLengthSid(pAccessSid)+GetLengthSid(pSystemSid); pipe_sd=(PSECURITY_DESCRIPTOR)malloc(sd_size); if(pipe_sd) { pAcl=(PACL)(((char *)pipe_sd)+SECURITY_DESCRIPTOR_MIN_LENGTH); if(!(InitializeAcl(pAcl,sd_size-SECURITY_DESCRIPTOR_MIN_LENGTH,ACL_REVISION)&&AddAccessAllowedAce(pAcl,ACL_REVISION,FILE_ALL_ACCESS,pAccessSid)&&AddAccessAllowedAce(pAcl,ACL_REVISION,FILE_ALL_ACCESS,pSystemSid)&&InitializeSecurityDescriptor(pipe_sd,SECURITY_DESCRIPTOR_REVISION)&&SetSecurityDescriptorDacl(pipe_sd,TRUE,pAcl,FALSE))) { free(pipe_sd); pipe_sd=NULL; } } FreeSid(pSystemSid); } FreeSid(pAccessSid); } } for(i=0;i<GetThreadCount();i++) { threads[i]=CreateThread(NULL,0,ServiceStartThread,(void *)(DWORD_PTR)i,CREATE_SUSPENDED,&ThreadID); if(threads[i]) { SetThreadPriority(threads[i],GetHearPriority()); ResumeThread(threads[i]); } } WaitStartEvent(aService); if(aService) ReportStatusToSCMgr(SERVICE_RUNNING,NO_ERROR,0); }
BOOL WipeFileW(wchar_t *filename) { DWORD Error=0,OldAttr,needed; void *SD=NULL; int correct_SD=FALSE; wchar_t dir[2*MAX_PATH],tmpname[MAX_PATH],*fileptr=wcsrchr(filename,L'\\'); unsigned char *buffer=(unsigned char *)malloc(BUFF_SIZE); if(fileptr&&buffer) { OldAttr=GetFileAttributesW(filename); SetFileAttributesW(filename,OldAttr&(~FILE_ATTRIBUTE_READONLY)); if(!GetFileSecurityW(filename,DACL_SECURITY_INFORMATION,NULL,0,&needed)) if(GetLastError()==ERROR_INSUFFICIENT_BUFFER) { SD=malloc(needed); if(SD) if(GetFileSecurityW(filename,DACL_SECURITY_INFORMATION,SD,needed,&needed)) correct_SD=TRUE; } wcsncpy(dir,filename,fileptr-filename+1); dir[fileptr-filename+1]=0; if(GetTempFileNameW(dir,L"bc",0,tmpname)) { if(MoveFileExW(filename,tmpname,MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH)) { HANDLE f=CreateFileW(tmpname,FILE_GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN,NULL); if(f!=INVALID_HANDLE_VALUE) { BY_HANDLE_FILE_INFORMATION info; if(GetFileInformationByHandle(f,&info)) { unsigned long long size=(unsigned long long)info.nFileSizeLow+(unsigned long long)info.nFileSizeHigh*4294967296ULL; unsigned long long processed_size=0; while(size) { unsigned long outsize=(unsigned long)((size>=BUFF_SIZE)?BUFF_SIZE:size),transferred; WriteFile(f,buffer,outsize,&transferred,NULL); size-=outsize; processed_size+=outsize; if(UpdatePosInfo(0ULL,processed_size)) break; } } if((SetFilePointer(f,0,NULL,FILE_BEGIN)==INVALID_SET_FILE_POINTER)||(!SetEndOfFile(f))) Error=GetLastError(); CloseHandle(f); } if(Error) MoveFileExW(tmpname,filename,MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH); else if(!DeleteFileW(tmpname)) Error=GetLastError(); } else { Error=GetLastError(); DeleteFileW(tmpname); } } else Error=GetLastError(); if(Error) { SetFileAttributesW(filename,OldAttr); if(correct_SD) SetFileSecurityW(filename,DACL_SECURITY_INFORMATION,SD); } } free(SD); free(buffer); if(Error) { SetLastError(Error); return FALSE; } return TRUE; }