static DWORD DeconstructSecurityDescriptor( DWORD dwLength, PSECURITY_DESCRIPTOR_RELATIVE pRelative, PDWORD pdwAllowUserCount, PWSTR** pppwszAllowUsers, PDWORD pdwDenyUserCount, PWSTR** pppwszDenyUsers, PBOOLEAN pbReadOnly ) { NTSTATUS status = STATUS_SUCCESS; DWORD dwError = 0; ULONG ulSize = 0; ULONG ulDaclSize = 0; ULONG ulSaclSize = 0; ULONG ulOwnerSize = 0; ULONG ulGroupSize = 0; PSID pOwner = NULL; PSID pGroup = NULL; PACL pSacl = NULL; PSECURITY_DESCRIPTOR_ABSOLUTE pAbsolute = NULL; PACL pDacl = NULL; ULONG ulIndex = 0; PVOID pAce = NULL; PACCESS_ALLOWED_ACE pAllow = NULL; PACCESS_DENIED_ACE pDeny = NULL; DWORD dwAllowUserCount = 0; PWSTR* ppwszAllowUsers = NULL; DWORD dwDenyUserCount = 0; PWSTR* ppwszDenyUsers = NULL; PSID pSid = NULL; PWSTR pwszUser = NULL; HANDLE hLsa = NULL; ACCESS_MASK leastMask = FILE_ALL_ACCESS; dwError = LsaOpenServer(&hLsa); BAIL_ON_LTNET_ERROR(dwError); status = RtlSelfRelativeToAbsoluteSD( pRelative, pAbsolute, &ulSize, pDacl, &ulDaclSize, pSacl, &ulSaclSize, pOwner, &ulOwnerSize, pGroup, &ulGroupSize); if (status != STATUS_BUFFER_TOO_SMALL) { dwError = LwNtStatusToWin32Error(status); BAIL_ON_LTNET_ERROR(dwError); } dwError = LwNetAllocateMemory(ulSize, OUT_PPVOID(&pAbsolute)); BAIL_ON_LTNET_ERROR(dwError); if (ulDaclSize) { dwError = LwNetAllocateMemory(ulDaclSize, OUT_PPVOID(&pDacl)); BAIL_ON_LTNET_ERROR(dwError); } if (ulSaclSize) { dwError = LwNetAllocateMemory(ulSaclSize, OUT_PPVOID(&pSacl)); BAIL_ON_LTNET_ERROR(dwError); } if (ulOwnerSize) { dwError = LwNetAllocateMemory(ulOwnerSize, OUT_PPVOID(&pOwner)); BAIL_ON_LTNET_ERROR(dwError); } if (ulGroupSize) { dwError = LwNetAllocateMemory(ulGroupSize, OUT_PPVOID(&pGroup)); BAIL_ON_LTNET_ERROR(dwError); } dwError = LwNtStatusToWin32Error( RtlSelfRelativeToAbsoluteSD( pRelative, pAbsolute, &ulSize, pDacl, &ulDaclSize, pSacl, &ulSaclSize, pOwner, &ulOwnerSize, pGroup, &ulGroupSize)); BAIL_ON_LTNET_ERROR(dwError); if (pDacl) { for (ulIndex = 0; ulIndex < RtlGetAclAceCount(pDacl); ulIndex++) { RtlGetAce(pDacl, ulIndex, &pAce); switch(((PACE_HEADER) pAce)->AceType) { case ACCESS_ALLOWED_ACE_TYPE: pAllow = pAce; pSid = (PSID) &pAllow->SidStart; if ((pAllow->Mask & FILE_GENERIC_READ) == FILE_GENERIC_READ) { dwError = MapSidToName(hLsa, pSid, &pwszUser); if (dwError != LW_ERROR_SUCCESS) { dwError = MapBuiltinSidToName(&pwszUser, pSid); } BAIL_ON_LTNET_ERROR(dwError); dwError = LwNetAppendStringArray( &dwAllowUserCount, &ppwszAllowUsers, pwszUser); BAIL_ON_LTNET_ERROR(dwError); pwszUser = NULL; leastMask &= pAllow->Mask; } break; case ACCESS_DENIED_ACE_TYPE: pDeny = pAce; pSid = (PSID) &pDeny->SidStart; if ((pDeny->Mask & FILE_GENERIC_READ) == FILE_GENERIC_READ) { dwError = MapSidToName(hLsa, pSid, &pwszUser); if (dwError != LW_ERROR_SUCCESS) { dwError = MapBuiltinSidToName(&pwszUser, pSid); } BAIL_ON_LTNET_ERROR(dwError); dwError = LwNetAppendStringArray( &dwDenyUserCount, &ppwszDenyUsers, pwszUser); BAIL_ON_LTNET_ERROR(dwError); pwszUser = NULL; } break; default: break; } } } *pppwszAllowUsers = ppwszAllowUsers; *pdwAllowUserCount = dwAllowUserCount; *pppwszDenyUsers = ppwszDenyUsers; *pdwDenyUserCount = dwDenyUserCount; *pbReadOnly = !((leastMask & FILE_GENERIC_WRITE) == FILE_GENERIC_WRITE); cleanup: if (hLsa) { LsaCloseServer(hLsa); } LTNET_SAFE_FREE_MEMORY(pSacl); LTNET_SAFE_FREE_MEMORY(pOwner); LTNET_SAFE_FREE_MEMORY(pGroup); LTNET_SAFE_FREE_MEMORY(pwszUser); LTNET_SAFE_FREE_MEMORY(pDacl); LTNET_SAFE_FREE_MEMORY(pAbsolute); return dwError; error: *pppwszAllowUsers = NULL; *pdwAllowUserCount = 0; *pppwszDenyUsers = NULL; *pdwDenyUserCount = 0; goto cleanup; }
static DWORD ConstructSecurityDescriptor( DWORD dwAllowUserCount, PWSTR* ppwszAllowUsers, DWORD dwDenyUserCount, PWSTR* ppwszDenyUsers, BOOLEAN bReadOnly, PSECURITY_DESCRIPTOR_RELATIVE* ppRelative, PDWORD pdwRelativeSize ) { DWORD dwError = 0; PSECURITY_DESCRIPTOR_ABSOLUTE pAbsolute = NULL; PSECURITY_DESCRIPTOR_RELATIVE pRelative = NULL; union { SID sid; BYTE buffer[SID_MAX_SIZE]; } Owner; union { SID sid; BYTE buffer[SID_MAX_SIZE]; } Group; ULONG OwnerSidSize = sizeof(Owner.buffer); ULONG GroupSidSize = sizeof(Group.buffer); DWORD dwDaclSize = 0; PACL pDacl = NULL; DWORD dwIndex = 0; PSID pSid = NULL; ULONG ulRelativeSize = 0; HANDLE hLsa = NULL; ACCESS_MASK mask = bReadOnly ? (FILE_GENERIC_READ|FILE_GENERIC_EXECUTE) : FILE_ALL_ACCESS; dwError = LsaOpenServer(&hLsa); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlCreateWellKnownSid( WinBuiltinAdministratorsSid, NULL, &Owner.sid, &OwnerSidSize)); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlCreateWellKnownSid( WinBuiltinPowerUsersSid, NULL, &Group.sid, &GroupSidSize)); BAIL_ON_LTNET_ERROR(dwError); dwDaclSize = ACL_HEADER_SIZE + dwAllowUserCount * (sizeof(ACCESS_ALLOWED_ACE) + SID_MAX_SIZE) + dwDenyUserCount * (sizeof(ACCESS_DENIED_ACE) + SID_MAX_SIZE) + RtlLengthSid(&Owner.sid) + RtlLengthSid(&Group.sid); dwError = LwNetAllocateMemory( dwDaclSize, OUT_PPVOID(&pDacl)); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlCreateAcl(pDacl, dwDaclSize, ACL_REVISION)); BAIL_ON_LTNET_ERROR(dwError); for (dwIndex = 0; dwIndex < dwDenyUserCount; dwIndex++) { dwError = MapNameToSid(hLsa, ppwszDenyUsers[dwIndex], &pSid); if (dwError != LW_ERROR_SUCCESS) { dwError = MapBuiltinNameToSid(&pSid, ppwszDenyUsers[dwIndex]); } BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlAddAccessDeniedAceEx( pDacl, ACL_REVISION, 0, FILE_ALL_ACCESS, pSid)); BAIL_ON_LTNET_ERROR(dwError); RTL_FREE(&pSid); } for (dwIndex = 0; dwIndex < dwAllowUserCount; dwIndex++) { dwError = MapNameToSid(hLsa, ppwszAllowUsers[dwIndex], &pSid); if (dwError != LW_ERROR_SUCCESS) { dwError = MapBuiltinNameToSid(&pSid, ppwszAllowUsers[dwIndex]); } BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlAddAccessAllowedAceEx( pDacl, ACL_REVISION, 0, mask, pSid)); BAIL_ON_LTNET_ERROR(dwError); RTL_FREE(&pSid); } dwError = LwNetAllocateMemory( SECURITY_DESCRIPTOR_ABSOLUTE_MIN_SIZE, OUT_PPVOID(&pAbsolute)); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlCreateSecurityDescriptorAbsolute( pAbsolute, SECURITY_DESCRIPTOR_REVISION)); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlSetOwnerSecurityDescriptor( pAbsolute, &Owner.sid, FALSE)); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlSetGroupSecurityDescriptor( pAbsolute, &Group.sid, FALSE)); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlSetDaclSecurityDescriptor( pAbsolute, TRUE, pDacl, FALSE)); BAIL_ON_LTNET_ERROR(dwError); RtlAbsoluteToSelfRelativeSD( pAbsolute, NULL, &ulRelativeSize); dwError = LwNetAllocateMemory(ulRelativeSize, OUT_PPVOID(&pRelative)); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlAbsoluteToSelfRelativeSD( pAbsolute, pRelative, &ulRelativeSize)); BAIL_ON_LTNET_ERROR(dwError); *ppRelative = pRelative; *pdwRelativeSize = ulRelativeSize; cleanup: if (hLsa) { LsaCloseServer(hLsa); } LTNET_SAFE_FREE_MEMORY(pSid); LTNET_SAFE_FREE_MEMORY(pDacl); LTNET_SAFE_FREE_MEMORY(pAbsolute); return dwError; error: *ppRelative = NULL; *pdwRelativeSize = 0; LTNET_SAFE_FREE_MEMORY(pRelative); goto cleanup; }
static DWORD NetShareParseArguments( int argc, char ** argv, PNET_SHARE_COMMAND_INFO* ppCommandInfo ) { DWORD dwError = 0; PNET_SHARE_COMMAND_INFO pCommandInfo = NULL; if (argc < 2) { dwError = LW_ERROR_INTERNAL; BAIL_ON_LTNET_ERROR(dwError); } dwError = LwNetAllocateMemory(sizeof(*pCommandInfo), (PVOID*)&pCommandInfo); BAIL_ON_LTNET_ERROR(dwError); if (!argv[2]) { pCommandInfo->dwControlCode = NET_SHARE_ENUM; goto cleanup; } if (!strcasecmp(argv[2], NET_SHARE_COMMAND_HELP)) { NetShareShowUsage(); goto cleanup; } else if (!strcasecmp(argv[2], NET_SHARE_COMMAND_ADD)) { pCommandInfo->dwControlCode = NET_SHARE_ADD; if (!argv[3]) { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LTNET_ERROR(dwError); } dwError = NetShareAddParseArguments(argc, argv, pCommandInfo); BAIL_ON_LTNET_ERROR(dwError); } else if (!strcasecmp(argv[2], NET_SHARE_COMMAND_DEL)) { pCommandInfo->dwControlCode = NET_SHARE_DEL; dwError = NetShareDelParseArguments(argc, argv, pCommandInfo); BAIL_ON_LTNET_ERROR(dwError); } else if (!strcasecmp(argv[2], "--server")) { pCommandInfo->dwControlCode = NET_SHARE_ENUM; dwError = NetShareEnumParseArguments(argc, argv, pCommandInfo); BAIL_ON_LTNET_ERROR(dwError); } else if (!strcasecmp(argv[2], NET_SHARE_COMMAND_SETINFO)) { pCommandInfo->dwControlCode = NET_SHARE_SETINFO; dwError = NetShareSetinfoParseArguments(argc, argv, pCommandInfo); BAIL_ON_LTNET_ERROR(dwError); } else if (!strcasecmp(argv[2], NET_SHARE_COMMAND_GETINFO)) { pCommandInfo->dwControlCode = NET_SHARE_GETINFO; dwError = NetShareGetinfoParseArguments(argc, argv, pCommandInfo); BAIL_ON_LTNET_ERROR(dwError); } else { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LTNET_ERROR(dwError); } cleanup: *ppCommandInfo = pCommandInfo; return dwError; error: if (LW_ERROR_INVALID_PARAMETER == dwError) { NetShareShowUsage(); } LTNET_SAFE_FREE_MEMORY(pCommandInfo); pCommandInfo = NULL; goto cleanup; }
DWORD NetExecShareEnum( NET_SHARE_ENUM_INFO_PARAMS ShareEnumInfo ) { static const DWORD dwLevel = 2; static const DWORD dwMaxLen = 1024; DWORD dwError = 0; PSHARE_INFO_2 pShareInfo = NULL; DWORD dwNumShares = 0; DWORD dwTotalShares = 0; DWORD dwVisitedShares = 0; DWORD dwResume = 0; DWORD dwIndex = 0; PSTR* ppszShareName = NULL; PSTR* ppszSharePath = NULL; PSTR* ppszShareComment = NULL; DWORD dwShareNameLenMax = 0; DWORD dwSharePathLenMax = 0; DWORD dwShareCommentLenMax = 0; DWORD dwShareNameLen = 0; DWORD dwSharePathLen = 0; DWORD dwShareCommentLen = 0; do { dwError = NetShareEnumW( ShareEnumInfo.pwszServerName, dwLevel, (PBYTE*)&pShareInfo, dwMaxLen, &dwNumShares, &dwTotalShares, &dwResume); if (dwError == ERROR_MORE_DATA) { dwError = 0; } BAIL_ON_LTNET_ERROR(dwError); if (!ppszShareName) { dwError = LwNetAllocateMemory((dwTotalShares+1)*sizeof(PCSTR), (PVOID *)&ppszShareName); BAIL_ON_LTNET_ERROR(dwError); } if (!ppszSharePath) { dwError = LwNetAllocateMemory((dwTotalShares+1)*sizeof(PCSTR), (PVOID *)&ppszSharePath); BAIL_ON_LTNET_ERROR(dwError); } if (!ppszShareComment) { dwError = LwNetAllocateMemory((dwTotalShares+1)*sizeof(PCSTR), (PVOID *)&ppszShareComment); BAIL_ON_LTNET_ERROR(dwError); } for (dwIndex = 0; dwIndex < dwNumShares; dwIndex++) { dwError = LwWc16sToMbs(pShareInfo[dwIndex].shi2_netname, &ppszShareName[dwIndex+dwVisitedShares]); BAIL_ON_LTNET_ERROR(dwError); dwError = LwWc16sToMbs(pShareInfo[dwIndex].shi2_path, &ppszSharePath[dwIndex+dwVisitedShares]); BAIL_ON_LTNET_ERROR(dwError); if (pShareInfo[dwIndex].shi2_remark) { dwError = LwWc16sToMbs(pShareInfo[dwIndex].shi2_remark, &ppszShareComment[dwIndex+dwVisitedShares]); BAIL_ON_LTNET_ERROR(dwError); } } if (pShareInfo) { NetApiBufferFree(pShareInfo); pShareInfo = NULL; } dwVisitedShares += dwNumShares; } while (dwVisitedShares < dwTotalShares); dwError = LwNetAllocateString(NET_SHARE_NAME_TITLE, &ppszShareName[dwTotalShares]); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNetAllocateString(NET_SHARE_PATH_TITLE, &ppszSharePath[dwTotalShares]); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNetAllocateString(NET_SHARE_COMMENT_TITLE, &ppszShareComment[dwTotalShares]); BAIL_ON_LTNET_ERROR(dwError); for (dwIndex = 0; dwIndex < dwTotalShares + 1; dwIndex++) { dwShareNameLen = strlen(ppszShareName[dwIndex]); if (dwShareNameLen>dwShareNameLenMax) { dwShareNameLenMax = dwShareNameLen; } dwSharePathLen = strlen(ppszSharePath[dwIndex]); if (dwSharePathLen>dwSharePathLenMax) { dwSharePathLenMax = dwSharePathLen; } if (ppszShareComment[dwIndex]) { dwShareCommentLen = strlen(ppszShareComment[dwIndex]); if (dwShareCommentLen>dwShareCommentLenMax) { dwShareCommentLenMax = dwShareCommentLen; } } } //print share enum header printf(" %s%*s", NET_SHARE_NAME_TITLE, (int) (strlen(NET_SHARE_NAME_TITLE)-dwShareNameLenMax), ""); printf(" %s%*s", NET_SHARE_PATH_TITLE, (int) (strlen(NET_SHARE_PATH_TITLE)-dwSharePathLenMax), ""); printf(" %s%*s\n", NET_SHARE_COMMENT_TITLE, (int) (strlen(NET_SHARE_COMMENT_TITLE)-dwShareCommentLenMax), ""); for (dwIndex = 0; dwIndex < dwShareNameLenMax+dwSharePathLenMax+dwShareCommentLenMax+10; dwIndex++) printf("%s", "-"); printf("\n"); for (dwIndex = 0; dwIndex < dwTotalShares; dwIndex++) { printf(" %s%*s", ppszShareName[dwIndex], (int) (strlen(ppszShareName[dwIndex])-dwShareNameLenMax), ""); printf(" %s%*s", ppszSharePath[dwIndex], (int) (strlen(ppszSharePath[dwIndex])-dwSharePathLenMax), ""); if (ppszShareComment[dwIndex]) { printf(" %s%*s", ppszShareComment[dwIndex], (int) (strlen(ppszShareComment[dwIndex])-dwShareCommentLenMax), ""); } printf("\n"); } cleanup: if (ppszShareName) { LwNetFreeStringArray(dwTotalShares, ppszShareName); } if (ppszSharePath) { LwNetFreeStringArray(dwTotalShares, ppszSharePath); } if (ppszShareComment) { LwNetFreeStringArray(dwTotalShares, ppszShareComment); } if (pShareInfo) { NetApiBufferFree(pShareInfo); pShareInfo = NULL; } return dwError; error: goto cleanup; }
static DWORD NetShareAddParseArguments( int argc, char** argv, IN OUT PNET_SHARE_COMMAND_INFO pCommandInfo ) { DWORD dwError = 0; PCSTR pszPath = NULL; size_t sShareNameLen = 0; int indexShareAddArg = 3; // Do not free PCSTR pszShareAddShareInfo = NULL; PSTR pszShareName = NULL; if (!argv[indexShareAddArg]) { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LTNET_ERROR(dwError); } if (!strncmp(argv[indexShareAddArg], "\\\\", sizeof("\\\\")-1)) { dwError = LwMbsToWc16s(argv[indexShareAddArg]+sizeof("\\\\")-1, &pCommandInfo->ShareAddOrSetInfo.pwszServerName); BAIL_ON_LTNET_ERROR(dwError); indexShareAddArg++; } if (indexShareAddArg > argc-1) { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LTNET_ERROR(dwError); } pszShareAddShareInfo = argv[indexShareAddArg]; pszPath = strchr(pszShareAddShareInfo, '='); if (LTNET_IS_NULL_OR_EMPTY_STR(pszPath)) { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LTNET_ERROR(dwError); } dwError = LwMbsToWc16s(pszPath+1, &pCommandInfo->ShareAddOrSetInfo.pwszPath); BAIL_ON_LTNET_ERROR(dwError); sShareNameLen = strlen(pszShareAddShareInfo)-strlen(pszPath); if (!sShareNameLen) { dwError = LW_ERROR_INVALID_PARAMETER; BAIL_ON_LTNET_ERROR(dwError); } dwError = LwNetAllocateMemory(sShareNameLen+1, (PVOID*)&pszShareName); BAIL_ON_LTNET_ERROR(dwError); memcpy(pszShareName, pszShareAddShareInfo, sShareNameLen); dwError = LwMbsToWc16s(pszShareName, &pCommandInfo->ShareAddOrSetInfo.pwszShareName); BAIL_ON_LTNET_ERROR(dwError); // Process add options dwError = ParseShareAddOrSetinfoOptionArgs(argc, ++indexShareAddArg, argv, pCommandInfo->dwControlCode, &pCommandInfo->ShareAddOrSetInfo); BAIL_ON_LTNET_ERROR(dwError); cleanup: LTNET_SAFE_FREE_STRING(pszShareName); return dwError; error: NetShareFreeCommandInfo(pCommandInfo); goto cleanup; }