DWORD NetShare( int argc, char ** argv ) { DWORD dwError = 0; PNET_SHARE_COMMAND_INFO pCommandInfo = NULL; dwError = NetShareParseArguments( argc, argv, &pCommandInfo ); BAIL_ON_LTNET_ERROR(dwError); dwError = NetShareInitialize(); BAIL_ON_LTNET_ERROR(dwError); switch (pCommandInfo->dwControlCode) { case NET_SHARE_ADD: dwError = NetExecShareAdd(pCommandInfo->ShareAddOrSetInfo); BAIL_ON_LTNET_ERROR(dwError); break; case NET_SHARE_DEL: dwError = NetExecShareDel(pCommandInfo->ShareDelInfo); BAIL_ON_LTNET_ERROR(dwError); break; case NET_SHARE_ENUM: dwError = NetExecShareEnum(pCommandInfo->ShareEnumInfo); BAIL_ON_LTNET_ERROR(dwError); break; case NET_SHARE_SETINFO: dwError = NetExecSetInfo(pCommandInfo->ShareAddOrSetInfo); BAIL_ON_LTNET_ERROR(dwError); break; default: break; } cleanup: NetShareFreeCommandInfo(pCommandInfo); LTNET_SAFE_FREE_MEMORY(pCommandInfo); pCommandInfo = NULL; return dwError; error: goto cleanup; }
static VOID NetShareFreeCommandInfo( PNET_SHARE_COMMAND_INFO pCommandInfo ) { if (!pCommandInfo) return; switch (pCommandInfo->dwControlCode) { case NET_SHARE_ADD: case NET_SHARE_SETINFO: LTNET_SAFE_FREE_MEMORY(pCommandInfo->ShareAddOrSetInfo.pwszServerName); LTNET_SAFE_FREE_MEMORY(pCommandInfo->ShareAddOrSetInfo.pwszPath); LTNET_SAFE_FREE_MEMORY(pCommandInfo->ShareAddOrSetInfo.pwszShareName); break; case NET_SHARE_DEL: LTNET_SAFE_FREE_MEMORY(pCommandInfo->ShareDelInfo.pwszServerName); LTNET_SAFE_FREE_MEMORY(pCommandInfo->ShareDelInfo.pwszShareName); break; case NET_SHARE_ENUM: LTNET_SAFE_FREE_MEMORY(pCommandInfo->ShareEnumInfo.pwszServerName); break; default: break; } return; }
DWORD NetExecShareAdd( NET_SHARE_ADD_OR_SET_INFO_PARAMS ShareAddInfo ) { static const DWORD dwLevel = 502; DWORD dwError = 0; SHARE_INFO_502 shareInfo = {0}; DWORD dwParmErr = 0; PSECURITY_DESCRIPTOR_RELATIVE pSecDesc = NULL; DWORD dwSecDescSize = 0; dwError = ConstructSecurityDescriptor( ShareAddInfo.dwAllowUserCount, ShareAddInfo.ppwszAllowUsers, ShareAddInfo.dwDenyUserCount, ShareAddInfo.ppwszDenyUsers, ShareAddInfo.bReadOnly && !ShareAddInfo.bReadWrite, &pSecDesc, &dwSecDescSize); BAIL_ON_LTNET_ERROR(dwError); shareInfo.shi502_netname = ShareAddInfo.pwszShareName ? ShareAddInfo.pwszShareName : ShareAddInfo.pwszTarget; shareInfo.shi502_path = ShareAddInfo.pwszPath; shareInfo.shi502_type = 0; // SHARE_SERVICE_DISK_SHARE shareInfo.shi502_remark = ShareAddInfo.pwszComment; shareInfo.shi502_reserved = dwSecDescSize; shareInfo.shi502_security_descriptor = (PBYTE) pSecDesc; dwError = NetShareAddW( ShareAddInfo.pwszServerName, dwLevel, (PBYTE)&shareInfo, &dwParmErr); BAIL_ON_LTNET_ERROR(dwError); cleanup: LTNET_SAFE_FREE_MEMORY(pSecDesc); return dwError; error: goto cleanup; }
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; }
DWORD NetExecSetInfo( NET_SHARE_ADD_OR_SET_INFO_PARAMS ShareSetInfo ) { static const DWORD dwLevel = 502; DWORD dwError = 0; SHARE_INFO_502 newShareInfo = {0}; PSHARE_INFO_502 pShareInfo = NULL; DWORD dwParmErr = 0; PSECURITY_DESCRIPTOR_RELATIVE pSecDesc = NULL; DWORD dwSecDescSize = 0; DWORD dwAllowUserCount = 0; PWSTR* ppwszAllowUsers = NULL; DWORD dwDenyUserCount = 0; PWSTR* ppwszDenyUsers = NULL; BOOLEAN bReadOnly = FALSE; dwError = NetShareGetInfoW( ShareSetInfo.pwszServerName, ShareSetInfo.pwszShareName, dwLevel, (PBYTE*)(&pShareInfo)); BAIL_ON_LTNET_ERROR(dwError); dwError = DeconstructSecurityDescriptor( pShareInfo->shi502_reserved, (PSECURITY_DESCRIPTOR_RELATIVE) pShareInfo->shi502_security_descriptor, &dwAllowUserCount, &ppwszAllowUsers, &dwDenyUserCount, &ppwszDenyUsers, &bReadOnly); BAIL_ON_LTNET_ERROR(dwError); newShareInfo = *pShareInfo; if (ShareSetInfo.pwszShareName) { newShareInfo.shi502_netname = ShareSetInfo.pwszShareName; } if (ShareSetInfo.pwszComment) { newShareInfo.shi502_remark = ShareSetInfo.pwszComment; } if (ShareSetInfo.pwszPath) { newShareInfo.shi502_path = ShareSetInfo.pwszPath; } dwError = ConstructSecurityDescriptor( ShareSetInfo.dwAllowUserCount || ShareSetInfo.bClearAllow ? ShareSetInfo.dwAllowUserCount : dwAllowUserCount, ShareSetInfo.dwAllowUserCount || ShareSetInfo.bClearAllow ? ShareSetInfo.ppwszAllowUsers : ppwszAllowUsers, ShareSetInfo.dwDenyUserCount || ShareSetInfo.bClearDeny ? ShareSetInfo.dwDenyUserCount : dwDenyUserCount, ShareSetInfo.dwDenyUserCount || ShareSetInfo.bClearDeny ? ShareSetInfo.ppwszDenyUsers : ppwszDenyUsers, ShareSetInfo.bReadOnly || ShareSetInfo.bReadWrite ? (ShareSetInfo.bReadOnly && !ShareSetInfo.bReadWrite) : bReadOnly, &pSecDesc, &dwSecDescSize); BAIL_ON_LTNET_ERROR(dwError); newShareInfo.shi502_type = pShareInfo->shi502_type; newShareInfo.shi502_reserved = dwSecDescSize; newShareInfo.shi502_security_descriptor = (PBYTE) pSecDesc; dwError = NetShareSetInfoW( ShareSetInfo.pwszServerName, ShareSetInfo.pwszShareName, dwLevel, (PBYTE)&newShareInfo, &dwParmErr); BAIL_ON_LTNET_ERROR(dwError); cleanup: if (pShareInfo) { LwNetFreeMemory(pShareInfo); } LwNetFreeWC16StringArray(dwAllowUserCount, ppwszAllowUsers); LwNetFreeWC16StringArray(dwDenyUserCount, ppwszDenyUsers); LTNET_SAFE_FREE_MEMORY(pSecDesc); return dwError; error: goto cleanup; }
static DWORD ParseShareAddOrSetinfoOptionArgs( IN int argc, IN int indexStart, IN char** argv, IN NET_SHARE_CTRL_CODE dwCtrlCode, IN OUT PNET_SHARE_ADD_OR_SET_INFO_PARAMS pShareAddOrSetParams ) { DWORD dwError = 0; DWORD dwIndex = 0; PWSTR pwszArg = NULL; for (dwIndex = indexStart; dwIndex < argc; dwIndex++) { if (!strcmp(argv[dwIndex], "--allow")) { dwError = LwMbsToWc16s(argv[++dwIndex], &pwszArg); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNetAppendStringArray( &pShareAddOrSetParams->dwAllowUserCount, &pShareAddOrSetParams->ppwszAllowUsers, pwszArg); BAIL_ON_LTNET_ERROR(dwError); pwszArg = NULL; } else if (!strcmp(argv[dwIndex], "--deny")) { dwError = LwMbsToWc16s(argv[++dwIndex], &pwszArg); BAIL_ON_LTNET_ERROR(dwError); dwError = LwNetAppendStringArray( &pShareAddOrSetParams->dwDenyUserCount, &pShareAddOrSetParams->ppwszDenyUsers, pwszArg); BAIL_ON_LTNET_ERROR(dwError); pwszArg = NULL; } else if (!strcmp(argv[dwIndex], "--comment")) { dwError = LwMbsToWc16s(argv[++dwIndex], &pShareAddOrSetParams->pwszComment); BAIL_ON_LTNET_ERROR(dwError); } else if (!strcmp(argv[dwIndex], "--read-only")) { pShareAddOrSetParams->bReadOnly = TRUE; } else if (!strcmp(argv[dwIndex], "--read-write")) { pShareAddOrSetParams->bReadWrite = TRUE; } else if (!strcmp(argv[dwIndex], "--clear-allow") && NET_SHARE_SETINFO == dwCtrlCode) { pShareAddOrSetParams->bClearAllow = TRUE; } else if (!strcmp(argv[dwIndex], "--clear-deny") && NET_SHARE_SETINFO == dwCtrlCode) { pShareAddOrSetParams->bClearDeny = TRUE; } else { dwError = LwMbsToWc16s(argv[dwIndex], &pShareAddOrSetParams->pwszTarget); BAIL_ON_LTNET_ERROR(dwError); break; } } error: LTNET_SAFE_FREE_MEMORY(pwszArg); return dwError; }
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; }