/* Editor Settings: expandtabs and use 4 spaces for indentation * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: * */ /* * Copyright Likewise Software 2004-2008 * All rights reserved. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the license, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy * of the GNU Lesser General Public License along with this program. If * not, see . * * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING * TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU * LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT * license@likewisesoftware.com */ /* TODO: - --read-only --read-write - --clear-allow --clear-deny */ #include "config.h" #include "srvsvcsys.h" #include #include #include #include #include #include #include #include #include #include static struct { PWSTR pwszServerName; DWORD dwAllowUserCount; PWSTR* ppwszAllowUsers; DWORD dwDenyUserCount; PWSTR* ppwszDenyUsers; PWSTR pwszName; PWSTR pwszPath; PWSTR pwszComment; PWSTR pwszTarget; BOOLEAN bReadOnly; BOOLEAN bReadWrite; BOOLEAN bClearAllow; BOOLEAN bClearDeny; } gState = {0}; static VOID FreeStringArray( DWORD dwCount, PWSTR* ppwszArray ) { DWORD dwIndex = 0; if (ppwszArray) { for (dwIndex = 0; dwIndex < dwCount; dwIndex++) { LW_SAFE_FREE_MEMORY(ppwszArray[dwIndex]); } LW_SAFE_FREE_MEMORY(ppwszArray); } } static DWORD AppendStringArray( PDWORD pdwCount, PWSTR** pppwszArray, PWSTR pwszString ) { DWORD dwError = 0; PWSTR* ppwszNewArray = NULL; dwError = LwReallocMemory( *pppwszArray, OUT_PPVOID(&ppwszNewArray), sizeof(*ppwszNewArray) * (*pdwCount + 1)); BAIL_ON_SRVSVC_ERROR(dwError); ppwszNewArray[(*pdwCount)++] = pwszString; *pppwszArray = ppwszNewArray; error: return dwError; } static DWORD PrintStringAttribute( PCSTR pszName, PCWSTR pwszValue ) { DWORD dwError = 0; PSTR pszValue = NULL; dwError = LwWc16sToMbs(pwszValue, &pszValue); BAIL_ON_SRVSVC_ERROR(dwError); printf("%s=%s\n", pszName, pszValue); error: LW_SAFE_FREE_STRING(pszValue); return dwError; } static VOID Usage( void ) { printf( "Usage: lw-share [ ... ] enum\n" " lw-share [ ... ] add [ ... ] \n" " lw-share [ ... ] del \n" " lw-share [ ... ] get-info \n" " lw-share [ ... ] set-info [ ... ] \n"); } static VOID Help( void ) { Usage(); printf("\n" "Options:\n" "\n" " --usage Show usage information\n" " --help Show this help information\n" " --server Specify target server (default: local machine)\n" "\n" "Options (add/set-info):\n" "\n" " --path Share path\n" " --comment Share comment\n" " --read-only Make share read-only\n" " --read-write Make share readable and writable (default)\n" " --allow Allow user/group access to share\n" " --deny Deny user/group access to share\n" "\n" "Options (set-ifno):\n" " --clear-allow Clear allowed list\n" " --clear-deny Clear denied list\n"); } static DWORD ParseShareArgs( int argc, char** ppszArgv ) { DWORD dwError = 0; DWORD dwIndex = 0; PWSTR pwszArg = NULL; for (dwIndex = 1; dwIndex < argc; dwIndex++) { if (!strcmp(ppszArgv[dwIndex], "--allow")) { dwError = LwMbsToWc16s(ppszArgv[++dwIndex], &pwszArg); BAIL_ON_SRVSVC_ERROR(dwError); dwError = AppendStringArray( &gState.dwAllowUserCount, &gState.ppwszAllowUsers, pwszArg); BAIL_ON_SRVSVC_ERROR(dwError); pwszArg = NULL; } else if (!strcmp(ppszArgv[dwIndex], "--deny")) { dwError = LwMbsToWc16s(ppszArgv[++dwIndex], &pwszArg); BAIL_ON_SRVSVC_ERROR(dwError); dwError = AppendStringArray( &gState.dwDenyUserCount, &gState.ppwszDenyUsers, pwszArg); BAIL_ON_SRVSVC_ERROR(dwError); pwszArg = NULL; } else if (!strcmp(ppszArgv[dwIndex], "--name")) { dwError = LwMbsToWc16s(ppszArgv[++dwIndex], &gState.pwszName); BAIL_ON_SRVSVC_ERROR(dwError); } else if (!strcmp(ppszArgv[dwIndex], "--path")) { dwError = LwMbsToWc16s(ppszArgv[++dwIndex], &gState.pwszPath); BAIL_ON_SRVSVC_ERROR(dwError); } else if (!strcmp(ppszArgv[dwIndex], "--comment")) { dwError = LwMbsToWc16s(ppszArgv[++dwIndex], &gState.pwszComment); BAIL_ON_SRVSVC_ERROR(dwError); } else if (!strcmp(ppszArgv[dwIndex], "--read-only")) { gState.bReadOnly = TRUE; } else if (!strcmp(ppszArgv[dwIndex], "--read-write")) { gState.bReadWrite = TRUE; } else if (!strcmp(ppszArgv[dwIndex], "--clear-allow")) { gState.bClearAllow = TRUE; } else if (!strcmp(ppszArgv[dwIndex], "--clear-deny")) { gState.bClearDeny = TRUE; } else { dwError = LwMbsToWc16s(ppszArgv[dwIndex], &gState.pwszTarget); BAIL_ON_SRVSVC_ERROR(dwError); break; } } error: LW_SAFE_FREE_MEMORY(pwszArg); return dwError; } static DWORD MapNameToSid( HANDLE hLsa, PCWSTR pwszName, PSID* ppSid ) { DWORD dwError = 0; PSTR pszName = NULL; LSA_QUERY_LIST QueryList; PLSA_SECURITY_OBJECT* ppObjects = NULL; dwError = LwWc16sToMbs(pwszName, &pszName); BAIL_ON_SRVSVC_ERROR(dwError); QueryList.ppszStrings = (PCSTR*) &pszName; dwError = LsaFindObjects( hLsa, NULL, 0, LSA_OBJECT_TYPE_UNDEFINED, LSA_QUERY_TYPE_BY_NAME, 1, QueryList, &ppObjects); BAIL_ON_SRVSVC_ERROR(dwError); if (ppObjects[0] == NULL) { dwError = LW_ERROR_NO_SUCH_OBJECT; BAIL_ON_SRVSVC_ERROR(dwError); } dwError = LwNtStatusToWin32Error( RtlAllocateSidFromCString(ppSid, ppObjects[0]->pszObjectSid)); BAIL_ON_SRVSVC_ERROR(dwError); cleanup: LsaFreeSecurityObjectList(1, ppObjects); LW_SAFE_FREE_STRING(pszName); return dwError; error: *ppSid = NULL; goto cleanup; } static DWORD MapSidToName( HANDLE hLsa, PSID pSid, PWSTR* ppwszName ) { DWORD dwError = 0; PSTR pszSid = NULL; LSA_QUERY_LIST QueryList; PLSA_SECURITY_OBJECT* ppObjects = NULL; dwError = LwNtStatusToWin32Error( RtlAllocateCStringFromSid(&pszSid, pSid)); BAIL_ON_SRVSVC_ERROR(dwError); QueryList.ppszStrings = (PCSTR*) &pszSid; dwError = LsaFindObjects( hLsa, NULL, 0, LSA_OBJECT_TYPE_UNDEFINED, LSA_QUERY_TYPE_BY_SID, 1, QueryList, &ppObjects); BAIL_ON_SRVSVC_ERROR(dwError); if (ppObjects[0] == NULL) { dwError = LW_ERROR_NO_SUCH_OBJECT; BAIL_ON_SRVSVC_ERROR(dwError); } dwError = LwNtStatusToWin32Error( LwRtlWC16StringAllocatePrintfW( ppwszName, L"%s\\%s", ppObjects[0]->pszNetbiosDomainName, ppObjects[0]->pszSamAccountName)); BAIL_ON_SRVSVC_ERROR(dwError); cleanup: LsaFreeSecurityObjectList(1, ppObjects); LW_SAFE_FREE_STRING(pszSid); return dwError; error: *ppwszName = NULL; goto cleanup; } static DWORD MapBuiltinNameToSid( PSID *ppSid, PCWSTR pwszName ) { DWORD dwError = 0; union { SID sid; BYTE buffer[SID_MAX_SIZE]; } Sid; ULONG SidSize = sizeof(Sid.buffer); PWSTR pwszEveryone = NULL; dwError = LwNtStatusToWin32Error( RtlWC16StringAllocateFromCString( &pwszEveryone, "Everyone")); BAIL_ON_SRVSVC_ERROR(dwError); if (LwRtlWC16StringIsEqual(pwszName, pwszEveryone, FALSE)) { dwError = LwNtStatusToWin32Error( RtlCreateWellKnownSid( WinWorldSid, NULL, &Sid.sid, &SidSize)); } BAIL_ON_SRVSVC_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlDuplicateSid(ppSid, &Sid.sid)); cleanup: LW_RTL_FREE(&pwszEveryone); return dwError; error: goto cleanup; } static DWORD MapBuiltinSidToName( PWSTR *ppwszName, PSID pSid ) { DWORD dwError = 0; union { SID sid; BYTE buffer[SID_MAX_SIZE]; } Sid; ULONG SidSize = sizeof(Sid.buffer); PWSTR pwszEveryone = NULL; dwError = LwNtStatusToWin32Error( RtlCreateWellKnownSid( WinWorldSid, NULL, &Sid.sid, &SidSize)); BAIL_ON_SRVSVC_ERROR(dwError); if (RtlEqualSid(&Sid.sid, pSid)) { dwError = LwNtStatusToWin32Error( RtlWC16StringAllocateFromCString( &pwszEveryone, "Everyone")); BAIL_ON_SRVSVC_ERROR(dwError); } *ppwszName = pwszEveryone; cleanup: return dwError; error: LW_RTL_FREE(&pwszEveryone); 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_SRVSVC_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlCreateWellKnownSid( WinBuiltinAdministratorsSid, NULL, &Owner.sid, &OwnerSidSize)); BAIL_ON_SRVSVC_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlCreateWellKnownSid( WinBuiltinPowerUsersSid, NULL, &Group.sid, &GroupSidSize)); BAIL_ON_SRVSVC_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 = LwAllocateMemory( dwDaclSize, OUT_PPVOID(&pDacl)); BAIL_ON_SRVSVC_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlCreateAcl(pDacl, dwDaclSize, ACL_REVISION)); BAIL_ON_SRVSVC_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_SRVSVC_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlAddAccessDeniedAceEx( pDacl, ACL_REVISION, 0, FILE_ALL_ACCESS, pSid)); BAIL_ON_SRVSVC_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_SRVSVC_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlAddAccessAllowedAceEx( pDacl, ACL_REVISION, 0, mask, pSid)); BAIL_ON_SRVSVC_ERROR(dwError); RTL_FREE(&pSid); } dwError = LwAllocateMemory( SECURITY_DESCRIPTOR_ABSOLUTE_MIN_SIZE, OUT_PPVOID(&pAbsolute)); BAIL_ON_SRVSVC_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlCreateSecurityDescriptorAbsolute( pAbsolute, SECURITY_DESCRIPTOR_REVISION)); BAIL_ON_SRVSVC_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlSetOwnerSecurityDescriptor( pAbsolute, &Owner.sid, FALSE)); BAIL_ON_SRVSVC_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlSetGroupSecurityDescriptor( pAbsolute, &Group.sid, FALSE)); BAIL_ON_SRVSVC_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlSetDaclSecurityDescriptor( pAbsolute, TRUE, pDacl, FALSE)); BAIL_ON_SRVSVC_ERROR(dwError); RtlAbsoluteToSelfRelativeSD( pAbsolute, NULL, &ulRelativeSize); dwError = LwAllocateMemory(ulRelativeSize, OUT_PPVOID(&pRelative)); BAIL_ON_SRVSVC_ERROR(dwError); dwError = LwNtStatusToWin32Error( RtlAbsoluteToSelfRelativeSD( pAbsolute, pRelative, &ulRelativeSize)); BAIL_ON_SRVSVC_ERROR(dwError); *ppRelative = pRelative; *pdwRelativeSize = ulRelativeSize; cleanup: if (hLsa) { LsaCloseServer(hLsa); } RTL_FREE(&pSid); LW_SAFE_FREE_MEMORY(pDacl); LW_SAFE_FREE_MEMORY(pAbsolute); return dwError; error: *ppRelative = NULL; *pdwRelativeSize = 0; LW_SAFE_FREE_MEMORY(pRelative); 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_SRVSVC_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_SRVSVC_ERROR(dwError); } dwError = LwAllocateMemory(ulSize, OUT_PPVOID(&pAbsolute)); BAIL_ON_SRVSVC_ERROR(dwError); if (ulDaclSize) { dwError = LwAllocateMemory(ulDaclSize, OUT_PPVOID(&pDacl)); BAIL_ON_SRVSVC_ERROR(dwError); } if (ulSaclSize) { dwError = LwAllocateMemory(ulSaclSize, OUT_PPVOID(&pSacl)); BAIL_ON_SRVSVC_ERROR(dwError); } if (ulOwnerSize) { dwError = LwAllocateMemory(ulOwnerSize, OUT_PPVOID(&pOwner)); BAIL_ON_SRVSVC_ERROR(dwError); } if (ulGroupSize) { dwError = LwAllocateMemory(ulGroupSize, OUT_PPVOID(&pGroup)); BAIL_ON_SRVSVC_ERROR(dwError); } dwError = LwNtStatusToWin32Error( RtlSelfRelativeToAbsoluteSD( pRelative, pAbsolute, &ulSize, pDacl, &ulDaclSize, pSacl, &ulSaclSize, pOwner, &ulOwnerSize, pGroup, &ulGroupSize)); BAIL_ON_SRVSVC_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_SRVSVC_ERROR(dwError); dwError = AppendStringArray( &dwAllowUserCount, &ppwszAllowUsers, pwszUser); BAIL_ON_SRVSVC_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_SRVSVC_ERROR(dwError); dwError = AppendStringArray( &dwDenyUserCount, &ppwszDenyUsers, pwszUser); BAIL_ON_SRVSVC_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); } LW_SAFE_FREE_MEMORY(pSacl); LW_SAFE_FREE_MEMORY(pOwner); LW_SAFE_FREE_MEMORY(pGroup); LW_SAFE_FREE_MEMORY(pwszUser); LW_SAFE_FREE_MEMORY(pDacl); LW_SAFE_FREE_MEMORY(pAbsolute); return dwError; error: *pppwszAllowUsers = NULL; *pdwAllowUserCount = 0; *pppwszDenyUsers = NULL; *pdwDenyUserCount = 0; goto cleanup; } static DWORD Enum( int argc, char** ppszArgv ) { static const DWORD dwLevel = 0; static const DWORD dwMaxLen = 128; DWORD dwError = 0; PSHARE_INFO_0 pShareInfo = NULL; DWORD dwNumEntries = 0; DWORD dwTotalEntries = 0; DWORD dwSeenEntries = 0; DWORD dwResume = 0; DWORD dwIndex = 0; PSTR pszShareName = NULL; do { dwError = NetShareEnum( gState.pwszServerName, dwLevel, OUT_PPVOID(&pShareInfo), dwMaxLen, &dwNumEntries, &dwTotalEntries, &dwResume); BAIL_ON_SRVSVC_ERROR(dwError); dwSeenEntries += dwNumEntries; for (dwIndex = 0; dwIndex < dwNumEntries; dwIndex++) { dwError = LwWc16sToMbs(pShareInfo[dwIndex].shi0_netname, &pszShareName); BAIL_ON_SRVSVC_ERROR(dwError); printf("%s\n", pszShareName); LW_SAFE_FREE_STRING(pszShareName); } if (pShareInfo) { SrvSvcFreeMemory(pShareInfo); pShareInfo = NULL; } } while (dwSeenEntries < dwTotalEntries); cleanup: LW_SAFE_FREE_STRING(pszShareName); if (pShareInfo) { SrvSvcFreeMemory(pShareInfo); pShareInfo = NULL; } return dwError; error: goto cleanup; } static DWORD GetInfo( int argc, char** ppszArgv ) { static const DWORD dwLevel = 502; DWORD dwError = 0; PSHARE_INFO_502 pShareInfo = NULL; PWSTR pwszShareName = NULL; DWORD dwAllowUserCount = 0; PWSTR* ppwszAllowUsers = NULL; DWORD dwDenyUserCount = 0; PWSTR* ppwszDenyUsers = NULL; DWORD dwIndex = 0; PSTR pszUserName = NULL; BOOLEAN bReadOnly = FALSE; dwError = LwMbsToWc16s(ppszArgv[1], &pwszShareName); BAIL_ON_SRVSVC_ERROR(dwError); dwError = NetShareGetInfo( gState.pwszServerName, pwszShareName, dwLevel, OUT_PPVOID(&pShareInfo)); BAIL_ON_SRVSVC_ERROR(dwError); dwError = PrintStringAttribute("name", pShareInfo->shi502_netname); BAIL_ON_SRVSVC_ERROR(dwError); dwError = PrintStringAttribute("path", pShareInfo->shi502_path); BAIL_ON_SRVSVC_ERROR(dwError); dwError = PrintStringAttribute("comment", pShareInfo->shi502_remark); BAIL_ON_SRVSVC_ERROR(dwError); if (pShareInfo->shi502_security_descriptor) { dwError = DeconstructSecurityDescriptor( pShareInfo->shi502_reserved, (PSECURITY_DESCRIPTOR_RELATIVE) pShareInfo->shi502_security_descriptor, &dwAllowUserCount, &ppwszAllowUsers, &dwDenyUserCount, &ppwszDenyUsers, &bReadOnly); BAIL_ON_SRVSVC_ERROR(dwError); if (dwAllowUserCount) { printf("allow="); for (dwIndex = 0; dwIndex < dwAllowUserCount; dwIndex++) { dwError = LwWc16sToMbs(ppwszAllowUsers[dwIndex], &pszUserName); BAIL_ON_SRVSVC_ERROR(dwError); printf("%s", pszUserName); if (dwIndex < dwAllowUserCount - 1) { printf(","); } } printf("\n"); } if (dwDenyUserCount) { printf("deny="); for (dwIndex = 0; dwIndex < dwDenyUserCount; dwIndex++) { dwError = LwWc16sToMbs(ppwszDenyUsers[dwIndex], &pszUserName); BAIL_ON_SRVSVC_ERROR(dwError); printf("%s", pszUserName); if (dwIndex < dwDenyUserCount - 1) { printf(","); } } printf("\n"); } printf("read_only=%s\n", bReadOnly ? "true" : "false"); } cleanup: if (pShareInfo) { SrvSvcFreeMemory(pShareInfo); } LW_SAFE_FREE_MEMORY(pwszShareName); FreeStringArray(dwAllowUserCount, ppwszAllowUsers); FreeStringArray(dwDenyUserCount, ppwszDenyUsers); return dwError; error: goto cleanup; } static DWORD SetInfo( int argc, char** ppszArgv ) { 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 = ParseShareArgs( argc, ppszArgv); BAIL_ON_SRVSVC_ERROR(dwError); dwError = NetShareGetInfo( gState.pwszServerName, gState.pwszTarget, dwLevel, OUT_PPVOID(&pShareInfo)); BAIL_ON_SRVSVC_ERROR(dwError); dwError = DeconstructSecurityDescriptor( pShareInfo->shi502_reserved, (PSECURITY_DESCRIPTOR_RELATIVE) pShareInfo->shi502_security_descriptor, &dwAllowUserCount, &ppwszAllowUsers, &dwDenyUserCount, &ppwszDenyUsers, &bReadOnly); BAIL_ON_SRVSVC_ERROR(dwError); newShareInfo = *pShareInfo; if (gState.pwszName) { newShareInfo.shi502_netname = gState.pwszName; } if (gState.pwszComment) { newShareInfo.shi502_remark = gState.pwszComment; } if (gState.pwszPath) { newShareInfo.shi502_path = gState.pwszPath; } dwError = ConstructSecurityDescriptor( gState.dwAllowUserCount || gState.bClearAllow ? gState.dwAllowUserCount : dwAllowUserCount, gState.dwAllowUserCount || gState.bClearAllow ? gState.ppwszAllowUsers : ppwszAllowUsers, gState.dwDenyUserCount || gState.bClearDeny ? gState.dwDenyUserCount : dwDenyUserCount, gState.dwDenyUserCount || gState.bClearDeny ? gState.ppwszDenyUsers : ppwszDenyUsers, gState.bReadOnly || gState.bReadWrite ? (gState.bReadOnly && !gState.bReadWrite) : bReadOnly, &pSecDesc, &dwSecDescSize); BAIL_ON_SRVSVC_ERROR(dwError); newShareInfo.shi502_reserved = dwSecDescSize; newShareInfo.shi502_security_descriptor = (PBYTE) pSecDesc; dwError = NetShareSetInfo( gState.pwszServerName, gState.pwszTarget, dwLevel, &newShareInfo, &dwParmErr); BAIL_ON_SRVSVC_ERROR(dwError); cleanup: if (pShareInfo) { SrvSvcFreeMemory(pShareInfo); } FreeStringArray(dwAllowUserCount, ppwszAllowUsers); FreeStringArray(dwDenyUserCount, ppwszDenyUsers); LW_SAFE_FREE_MEMORY(pSecDesc); return dwError; error: goto cleanup; } static DWORD Add( int argc, char** ppszArgv ) { 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 = ParseShareArgs( argc, ppszArgv); BAIL_ON_SRVSVC_ERROR(dwError); dwError = ConstructSecurityDescriptor( gState.dwAllowUserCount, gState.ppwszAllowUsers, gState.dwDenyUserCount, gState.ppwszDenyUsers, gState.bReadOnly && !gState.bReadWrite, &pSecDesc, &dwSecDescSize); BAIL_ON_SRVSVC_ERROR(dwError); shareInfo.shi502_type = 0; // SHARE_SERVICE_DISK_SHARE shareInfo.shi502_netname = gState.pwszName ? gState.pwszName : gState.pwszTarget; shareInfo.shi502_remark = gState.pwszComment; shareInfo.shi502_path = gState.pwszPath; shareInfo.shi502_reserved = dwSecDescSize; shareInfo.shi502_security_descriptor = (PBYTE) pSecDesc; dwError = NetShareAdd( gState.pwszServerName, dwLevel, &shareInfo, &dwParmErr); BAIL_ON_SRVSVC_ERROR(dwError); cleanup: LW_SAFE_FREE_MEMORY(pSecDesc); return dwError; error: goto cleanup; } static DWORD Del( int argc, char** ppszArgv ) { DWORD dwError = 0; PWSTR pwszShareName = NULL; dwError = LwMbsToWc16s(ppszArgv[1], &pwszShareName); BAIL_ON_SRVSVC_ERROR(dwError); dwError = NetShareDel( gState.pwszServerName, pwszShareName, 0); BAIL_ON_SRVSVC_ERROR(dwError); cleanup: LW_SAFE_FREE_MEMORY(pwszShareName); return dwError; error: goto cleanup; } int main( int argc, char** ppszArgv ) { DWORD dwError = 0; DWORD dwIndex = 0; dwError = SrvSvcInitMemory(); BAIL_ON_SRVSVC_ERROR(dwError); if (argc < 2) { Usage(); return 1; } for (dwIndex = 1; dwIndex < argc; dwIndex++) { if (!strcasecmp(ppszArgv[dwIndex], "--server")) { dwError = LwMbsToWc16s(ppszArgv[++dwIndex], &gState.pwszServerName); BAIL_ON_SRVSVC_ERROR(dwError); } else if (!strcasecmp(ppszArgv[dwIndex], "--help")) { Help(); return 1; } else if (!strcasecmp(ppszArgv[dwIndex], "--usage")) { Help(); return 1; } else if (!strcasecmp(ppszArgv[dwIndex], "enum")) { dwError = Enum(argc - dwIndex, ppszArgv + dwIndex); BAIL_ON_SRVSVC_ERROR(dwError); break; } else if (!strcasecmp(ppszArgv[dwIndex], "get-info")) { dwError = GetInfo(argc - dwIndex, ppszArgv + dwIndex); BAIL_ON_SRVSVC_ERROR(dwError); break; } else if (!strcasecmp(ppszArgv[dwIndex], "set-info")) { dwError = SetInfo(argc - dwIndex, ppszArgv + dwIndex); BAIL_ON_SRVSVC_ERROR(dwError); break; } else if (!strcasecmp(ppszArgv[dwIndex], "add")) { dwError = Add(argc - dwIndex, ppszArgv + dwIndex); BAIL_ON_SRVSVC_ERROR(dwError); break; } else if (!strcasecmp(ppszArgv[dwIndex], "del")) { dwError = Del(argc - dwIndex, ppszArgv + dwIndex); BAIL_ON_SRVSVC_ERROR(dwError); break; } else { Usage(); return 1; } } error: if (dwError) { fprintf(stderr, "%s\n", LwWin32ExtErrorToName(dwError)); return 1; } else { return 0; } } /* local variables: mode: c c-basic-offset: 4 indent-tabs-mode: nil tab-width: 4 end: */