📄 smpd_adreg.cpp
字号:
if (NULL == pwszComputerName) { result = SMPD_FALSE; goto fn_exit; } /* Get the DN account name of the computer object for the server. */ if (!GetComputerObjectNameW(NameFullyQualifiedDN, pwszComputerName, &dwLen)) { delete pwszComputerName; result = SMPD_FALSE; goto fn_exit; } /*wprintf(L"GetComputerObjectName: %s\n", pwszComputerName);*/ dwStatus = SpnCompose( &pspn, /* Receives pointer to the SPN array. */ &ulSpn, /* Receives number of SPNs returned. */ szDNofSCP, /* Input: DN of the SCP. */ TEXT(SMPD_SERVICE_NAME)); /* Input: the service's class string. */ if (dwStatus != NO_ERROR) { ReportError(TEXT("Failed to compose SPN"), dwStatus); result = SMPD_FALSE; goto fn_exit; } if (dwStatus == NO_ERROR) { /*dwStatus = SpnRegister(pwszComputerName, pspn, ulSpn, DS_SPN_DELETE_SPN_OP);*/ dwStatus = SpnRegister(pwszComputerName, pspn, ulSpn, DS_SPN_ADD_SPN_OP); if (dwStatus != NO_ERROR) { ReportError(TEXT("SpnRegister failed"), dwStatus); delete pwszComputerName; result = SMPD_FALSE; goto fn_exit; } } delete pwszComputerName;fn_exit: CoUninitialize(); return result;}SMPD_BOOL smpd_remove_scp(){ DWORD dwStatus; LPWSTR pwszComputerName = NULL; LPWSTR pwszDnsComputerName = NULL; char *pszDnsComputerName = NULL; DWORD dwLen, dwMaxLen; SMPD_BOOL result = SMPD_TRUE; char spn[SMPD_MAX_NAME_LENGTH] = ""; WCHAR wspn[SMPD_MAX_NAME_LENGTH] = L""; WCHAR* pwspn[1]; /* FIXME: Insert code here to remove the information created by ScpCreate */ /* Get the size required for the DN account name. */ dwLen = 0; GetComputerObjectNameW(NameFullyQualifiedDN, NULL, &dwLen); pwszComputerName = new WCHAR[dwLen + 1]; if (NULL == pwszComputerName) { result = SMPD_FALSE; goto fn_exit; } /* Get the DN account name of the computer object for the server. */ if (!GetComputerObjectNameW(NameFullyQualifiedDN, pwszComputerName, &dwLen)) { result = SMPD_FALSE; goto fn_exit; } /*wprintf(L"GetComputerObjectName: %s\n", pwszComputerName);*/ /* Get the size required for the DNS account name. */ dwLen = 0; GetComputerNameExW(ComputerNameDnsFullyQualified, NULL, &dwLen); dwMaxLen = dwLen+1; pwszDnsComputerName = new WCHAR[dwLen + 1]; if (NULL == pwszDnsComputerName) { result = SMPD_FALSE; goto fn_exit; } pszDnsComputerName = new char[dwLen + 1]; if (NULL == pszDnsComputerName) { result = SMPD_FALSE; goto fn_exit; } /* Get the DNS account name of the computer object for the server. */ if (!GetComputerNameExW(ComputerNameDnsFullyQualified, pwszDnsComputerName, &dwLen)) { result = SMPD_FALSE; goto fn_exit; } wcstombs(pszDnsComputerName, pwszDnsComputerName, dwMaxLen); /*wprintf(L"GetComputerNameEx: %s\n", pwszDnsComputerName);*/ result = smpd_lookup_spn(spn, SMPD_MAX_NAME_LENGTH, pszDnsComputerName, SMPD_LISTENER_PORT); if (result != SMPD_SUCCESS) { smpd_err_printf("unable to lookup the smpd Service Principal Name for %s.\n", pszDnsComputerName); result = SMPD_FALSE; goto fn_exit; } result = SMPD_TRUE; mbstowcs(wspn, spn, SMPD_MAX_NAME_LENGTH); pwspn[0] = wspn; dwStatus = SpnRegister(pwszComputerName, pwspn, 1, DS_SPN_DELETE_SPN_OP); if (dwStatus != NO_ERROR) { ReportError(TEXT("SpnRegister failed"), dwStatus); result = SMPD_FALSE; }fn_exit: if (pwszComputerName) delete pwszComputerName; if (pwszDnsComputerName) delete pwszDnsComputerName; if (pszDnsComputerName) delete pszDnsComputerName; return result;}DWORD smpd_scp_update(USHORT usPort){ DWORD dwStat, dwType, dwLen; BOOL bUpdate=FALSE; HKEY hReg; TCHAR szAdsPath[MAX_PATH]; TCHAR szServer[MAX_PATH]; TCHAR szPort[8]; TCHAR *pszAttrs[]={ {TEXT("serviceDNSName")}, {TEXT("serviceBindingInformation")}, }; HRESULT hr; IDirectoryObject *pObj; DWORD dwAttrs; int i; PADS_ATTR_INFO pAttribs; ADSVALUE dnsname,binding; ADS_ATTR_INFO Attribs[] ={ {TEXT("serviceDnsName"),ADS_ATTR_UPDATE,ADSTYPE_CASE_IGNORE_STRING,&dnsname,1}, {TEXT("serviceBindingInformation"),ADS_ATTR_UPDATE,ADSTYPE_CASE_IGNORE_STRING,&binding,1}, }; /* Open the service registry key. */ dwStat = RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT(SMPD_SERVICE_REGISTRY_KEY), 0, KEY_QUERY_VALUE, &hReg); if (dwStat != NO_ERROR) { ReportServiceError("RegOpenKeyEx failed", dwStat); return dwStat; } /* Get the GUID binding string used to bind to the service SCP. */ dwLen = sizeof(szAdsPath); dwStat = RegQueryValueEx(hReg, TEXT("GUIDBindingString"), 0, &dwType, (LPBYTE)szAdsPath, &dwLen); if (dwStat != NO_ERROR){ ReportServiceError("RegQueryValueEx failed", dwStat); return dwStat; } RegCloseKey(hReg); /* Bind to the SCP. */ hr = ADsGetObject(szAdsPath, IID_IDirectoryObject, (void **)&pObj); if (FAILED(hr)) { char szMsg1[1024]; sprintf(szMsg1, "ADsGetObject failed to bind to GUID (bind string: %S): ", szAdsPath); ReportServiceError(szMsg1, hr); if (pObj) { pObj->Release(); } return dwStat; } /* Retrieve attributes from the SCP. */ hr = pObj->GetObjectAttributes(pszAttrs, 2, &pAttribs, &dwAttrs); if (FAILED(hr)){ ReportServiceError("GetObjectAttributes failed", hr); pObj->Release(); return hr; } /* Get the current port and DNS name of the host server. */ _sntprintf(szPort, 8, TEXT("%d"), usPort); dwLen = sizeof(szServer); if (!GetComputerNameEx(ComputerNameDnsFullyQualified,szServer,&dwLen)) { pObj->Release(); return GetLastError(); } /* Compare the current DNS name and port to the values retrieved from the SCP. Update the SCP only if nothing has changed. */ for (i=0; i<(LONG)dwAttrs; i++) { if ((_tcscmp(TEXT("serviceDNSName"),pAttribs[i].pszAttrName)==0) && (pAttribs[i].dwADsType == ADSTYPE_CASE_IGNORE_STRING)) { if (_tcscmp(szServer,pAttribs[i].pADsValues->CaseIgnoreString) != 0) { ReportServiceError("serviceDNSName being updated", 0); bUpdate = TRUE; } else { ReportServiceError("serviceDNSName okay", 0); } } if ((_tcscmp(TEXT("serviceBindingInformation"),pAttribs[i].pszAttrName)==0) && (pAttribs[i].dwADsType == ADSTYPE_CASE_IGNORE_STRING)) { if (_tcscmp(szPort,pAttribs[i].pADsValues->CaseIgnoreString) != 0) { ReportServiceError("serviceBindingInformation being updated", 0); bUpdate = TRUE; } else { ReportServiceError("serviceBindingInformation okay", 0); } } } FreeADsMem(pAttribs); /* The binding data or server name have changed, so update the SCP values. */ if (bUpdate) { dnsname.dwType = ADSTYPE_CASE_IGNORE_STRING; dnsname.CaseIgnoreString = szServer; binding.dwType = ADSTYPE_CASE_IGNORE_STRING; binding.CaseIgnoreString = szPort; hr = pObj->SetObjectAttributes(Attribs, 2, &dwAttrs); if (FAILED(hr)) { ReportServiceError("ScpUpdate: Failed to set SCP values.", hr); pObj->Release(); return hr; } } pObj->Release(); return dwStat;}static HRESULT AllowAccessToScpProperties( LPWSTR wszAccountSAM, /* Service account to allow access. */ IADs *pSCPObject) /* IADs pointer to the SCP object. */{ HRESULT hr = E_FAIL; IADsAccessControlList *pACL = NULL; IADsSecurityDescriptor *pSD = NULL; IDispatch *pDisp = NULL; IADsAccessControlEntry *pACE1 = NULL; IADsAccessControlEntry *pACE2 = NULL; IDispatch *pDispACE = NULL; CComBSTR sbstrTrustee; CComBSTR sbstrSecurityDescriptor = L"nTSecurityDescriptor"; VARIANT varSD; if (NULL == pSCPObject) { return E_INVALIDARG; } VariantInit(&varSD); /* If no service account is specified, service runs under LocalSystem. Allow access to the computer account of the service's host. */ if (wszAccountSAM) { sbstrTrustee = wszAccountSAM; } else { LPWSTR pwszComputerName; DWORD dwLen; /* Get the size required for the SAM account name. */ dwLen = 0; GetComputerObjectNameW(NameSamCompatible, NULL, &dwLen); pwszComputerName = new WCHAR[dwLen + 1]; if (NULL == pwszComputerName) { hr = E_OUTOFMEMORY; goto cleanup; } /* Get the SAM account name of the computer object for the server. */ if (!GetComputerObjectNameW(NameSamCompatible, pwszComputerName, &dwLen)) { delete pwszComputerName; hr = HRESULT_FROM_WIN32(GetLastError()); goto cleanup; } sbstrTrustee = pwszComputerName; /*wprintf(L"GetComputerObjectName: %s\n", pwszComputerName);*/ } /* Get the nTSecurityDescriptor. */ hr = pSCPObject->Get(sbstrSecurityDescriptor, &varSD); if (FAILED(hr) || (varSD.vt != VT_DISPATCH)) { _tprintf(TEXT("Get nTSecurityDescriptor failed: 0x%x\n"), hr); goto cleanup; } /* Use the V_DISPATCH macro to get the IDispatch pointer from VARIANT structure and QueryInterface for an IADsSecurityDescriptor pointer. */ hr = V_DISPATCH( &varSD )->QueryInterface( IID_IADsSecurityDescriptor, (void**)&pSD); if (FAILED(hr)) { _tprintf(TEXT("Cannot get IADsSecurityDescriptor: 0x%x\n"), hr); goto cleanup; } /* Get an IADsAccessControlList pointer to the security descriptor's DACL. */ hr = pSD->get_DiscretionaryAcl(&pDisp); if (SUCCEEDED(hr)) { hr = pDisp->QueryInterface( IID_IADsAccessControlList, (void**)&pACL); } if (FAILED(hr)) { _tprintf(TEXT("Cannot get DACL: 0x%x\n"), hr); goto cleanup; } /* Create the COM object for the first ACE. */ hr = CoCreateInstance(CLSID_AccessControlEntry, NULL, CLSCTX_INPROC_SERVER, IID_IADsAccessControlEntry, (void **)&pACE1); /* Create the COM object for the second ACE. */ if (SUCCEEDED(hr)) { hr = CoCreateInstance(CLSID_AccessControlEntry, NULL, CLSCTX_INPROC_SERVER, IID_IADsAccessControlEntry, (void **)&pACE2); } if (FAILED(hr)) { _tprintf(TEXT("Cannot create ACEs: 0x%x\n"), hr); goto cleanup; } /* Set the properties of the two ACEs. */ /* Allow read and write access to the property. */ hr = pACE1->put_AccessMask( ADS_RIGHT_DS_READ_PROP | ADS_RIGHT_DS_WRITE_PROP); hr = pACE2->put_AccessMask( ADS_RIGHT_DS_READ_PROP | ADS_RIGHT_DS_WRITE_PROP); /* Set the trustee, which is either the service account or the host computer account. */ hr = pACE1->put_Trustee( sbstrTrustee ); hr = pACE2->put_Trustee( sbstrTrustee ); /* Set the ACE type. */ hr = pACE1->put_AceType( ADS_ACETYPE_ACCESS_ALLOWED_OBJECT ); hr = pACE2->put_AceType( ADS_ACETYPE_ACCESS_ALLOWED_OBJECT ); /* Set AceFlags to zero because ACE is not inheritable. */ hr = pACE1->put_AceFlags( 0 ); hr = pACE2->put_AceFlags( 0 ); /* Set Flags to indicate an ACE that protects a specified object. */ hr = pACE1->put_Flags( ADS_FLAG_OBJECT_TYPE_PRESENT ); hr = pACE2->put_Flags( ADS_FLAG_OBJECT_TYPE_PRESENT ); /* Set ObjectType to the schemaIDGUID of the attribute. serviceDNSName */ hr = pACE1->put_ObjectType( L"{28630eb8-41d5-11d1-a9c1-0000f80367c1}"); /* serviceBindingInformation */ hr = pACE2->put_ObjectType( L"{b7b1311c-b82e-11d0-afee-0000f80367c1}"); /* Add the ACEs to the DACL. Need an IDispatch pointer for each ACE to pass to the AddAce method. */ hr = pACE1->QueryInterface(IID_IDispatch,(void**)&pDispACE); if (SUCCEEDED(hr)) { hr = pACL->AddAce(pDispACE); } if (FAILED(hr)) { _tprintf(TEXT("Cannot add first ACE: 0x%x\n"), hr); goto cleanup; } else { if (pDispACE) pDispACE->Release(); pDispACE = NULL; } /* Repeat for the second ACE. */ hr = pACE2->QueryInterface(IID_IDispatch, (void**)&pDispACE); if (SUCCEEDED(hr)) { hr = pACL->AddAce(pDispACE); } if (FAILED(hr)) { _tprintf(TEXT("Cannot add second ACE: 0x%x\n"), hr); goto cleanup; } /* Write the modified DACL back to the security descriptor. */ hr = pSD->put_DiscretionaryAcl(pDisp); if (SUCCEEDED(hr)) { /* Write the ntSecurityDescriptor property to the property cache. */ hr = pSCPObject->Put(sbstrSecurityDescriptor, varSD); if (SUCCEEDED(hr)) { /* SetInfo updates the SCP object in the directory. */ hr = pSCPObject->SetInfo(); } }cleanup: if (pDispACE) pDispACE->Release(); if (pACE1) pACE1->Release(); if (pACE2) pACE2->Release(); if (pACL) pACL->Release(); if (pDisp) pDisp->Release(); if (pSD) pSD->Release(); VariantClear(&varSD); return hr;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -