bool LdapUtils::getDcName(const char* domain, StringBuffer& dc) { bool ret = false; #ifdef _WIN32 PDOMAIN_CONTROLLER_INFO psInfo = NULL; DWORD dwErr = DsGetDcName(NULL, domain, NULL, NULL, DS_FORCE_REDISCOVERY | DS_DIRECTORY_SERVICE_REQUIRED, &psInfo); if( dwErr == NO_ERROR) { const char* dcname = psInfo->DomainControllerName; if(dcname != NULL) { while(*dcname == '\\') dcname++; dc.append(dcname); ret = true; } NetApiBufferFree(psInfo); } else { DBGLOG("Error getting domain controller, error = %d", dwErr); ret = false; } #endif return ret; }
// Creates a spn if the user hasn't specified one. void MakeSpn(unsigned char **pszSpn) { DWORD status = ERROR_SUCCESS; ULONG ulSpn = 1; unsigned char ** arrSpn = NULL; HANDLE hDS; PDOMAIN_CONTROLLER_INFO pDomainControllerInfo; char lpCompDN[128]; ULONG ulCompDNSize = sizeof(lpCompDN); BOOL NoFailure = TRUE; status = DsGetSpn(DS_SPN_NB_HOST, "dynept", NULL, // DN of this service. 0, // Use the default instance port. 0, // Number of additional instance names. NULL, // No additional instance names. NULL, // No additional instance ports. &ulSpn, // Size of SPN array. &arrSpn); // Returned SPN(s). printf_s("DsGetSpn returned 0x%x\n", status); if (status != ERROR_SUCCESS) { exit(status); } // Get the name of domain if it is domain-joined if (status = DsGetDcName(NULL, NULL, NULL, NULL, DS_RETURN_DNS_NAME, &pDomainControllerInfo) != NO_ERROR) { printf_s("DsGetDcName returned %d\n", GetLastError()); NoFailure = FALSE; } // if it is domain joined if (NoFailure) { // Bind to the domain controller for our domain if ((status = DsBind(NULL, pDomainControllerInfo->DomainName, &hDS)) != ERROR_SUCCESS) { printf_s("DsBind returned %d\n", GetLastError()); NoFailure = FALSE; } } if (NoFailure) { if ((status = NetApiBufferFree(pDomainControllerInfo)) != NERR_Success) { printf_s("NetApiBufferFree returned %d\n", status); exit(status); } if (GetComputerObjectName(NameFullyQualifiedDN, lpCompDN, &ulCompDNSize) == 0) { printf_s("GetComputerObjectName returned %d\n", GetLastError()); exit(status); } /* We could check whether the SPN is already registered for this computer's DN, but we don't have to. Modification is performed permissiely by this function, so that adding a value that already exists does not return an error. This way we can opt for the internal check instead of doing it ourselves. */ status = DsWriteAccountSpn(hDS, DS_SPN_ADD_SPN_OP, lpCompDN, ulSpn, arrSpn); if (status != NO_ERROR) { printf_s("DsWriteAccountSpn returned %d\n", status); exit(status); } DsUnBind(&hDS); } *pszSpn = *arrSpn; }
int smpd_register_spn(const char *dc, const char *dn, const char *dh) { DWORD len; char err_msg[256]; LPSTR *spns; HANDLE ds; DWORD result; char domain_controller[SMPD_MAX_HOST_LENGTH] = ""; char domain_name[SMPD_MAX_HOST_LENGTH] = ""; char domain_host[SMPD_MAX_HOST_LENGTH] = ""; char host[SMPD_MAX_HOST_LENGTH] = ""; int really = 0; char *really_env; PDOMAIN_CONTROLLER_INFO pInfo; result = DsGetDcName(NULL/*local computer*/, NULL, NULL, NULL, /*DS_IS_FLAT_NAME | DS_RETURN_DNS_NAME | DS_DIRECTORY_SERVICE_REQUIRED, */ DS_DIRECTORY_SERVICE_REQUIRED | DS_KDC_REQUIRED, &pInfo); if (result == ERROR_SUCCESS) { strcpy(domain_controller, pInfo->DomainControllerName); strcpy(domain_name, pInfo->DomainName); NetApiBufferFree(pInfo); } if (dc && *dc != '\0') { strcpy(domain_controller, dc); } if (dn && *dn != '\0') { strcpy(domain_name, dn); } if (dh && *dh != '\0') { strcpy(domain_host, dh); } if (domain_host[0] == '\0') { smpd_get_hostname(host, SMPD_MAX_HOST_LENGTH); if (domain_name[0] != '\0') { sprintf(domain_host, "%s\\%s", domain_name, host); } else { strcpy(domain_host, host); } } printf("DsBind(%s, %s, ...)\n", domain_controller[0] == '\0' ? NULL : domain_controller, domain_name[0] == '\0' ? NULL : domain_name); result = DsBind( domain_controller[0] == '\0' ? NULL : domain_controller, domain_name[0] == '\0' ? NULL : domain_name, &ds); if (result != ERROR_SUCCESS) { smpd_translate_win_error(result, err_msg, 256, NULL); smpd_err_printf("DsBind failed: %s\n", err_msg); return SMPD_FAIL; } really_env = getenv("really"); if (really_env) really = 1; #if 1 len = 1; /*result = DsGetSpn(DS_SPN_SERVICE, SMPD_SERVICE_NAME, SMPD_SERVICE_NAME, 0, 0, NULL, NULL, &len, &spns);*/ result = DsGetSpn(DS_SPN_DNS_HOST, SMPD_SERVICE_NAME, NULL, SMPD_LISTENER_PORT, 0, NULL, NULL, &len, &spns); if (result != ERROR_SUCCESS) { smpd_translate_win_error(result, err_msg, 256, NULL); smpd_err_printf("DsGetSpn failed: %s\n", err_msg); return SMPD_FAIL; } if (really) { printf("registering: %s\n", spns[0]); len = SMPD_MAX_HOST_LENGTH; GetComputerObjectName(NameFullyQualifiedDN, domain_host, &len); printf("on account: %s\n", domain_host); result = DsWriteAccountSpn(ds, DS_SPN_ADD_SPN_OP, domain_host, 1, (LPCSTR*)spns); if (result != ERROR_SUCCESS) { DsFreeSpnArray(1, spns); smpd_translate_win_error(result, err_msg, 256, NULL); smpd_err_printf("DsWriteAccountSpn failed: %s\n", err_msg); return SMPD_FAIL; } } else { printf("would register '%s' on %s\n", spns[0], domain_host); } DsFreeSpnArray(1, spns); #else if (really) { result = DsServerRegisterSpn(DS_SPN_ADD_SPN_OP, SMPD_SERVICE_NAME, domain_host); if (result != ERROR_SUCCESS) { smpd_translate_win_error(result, err_msg, 256, NULL); smpd_err_printf("DsServerRegisterSpn failed: %s\n", err_msg); return SMPD_FAIL; } } else { printf("would register '%s' on %s\n", SMPD_SERVICE_NAME, domain_host); } #endif result = DsUnBind(&ds); return SMPD_SUCCESS; }
int main(int argc, char * argv[]) { EncryptionKey userKey; LPCSTR szUser, szDomain, szTarget, szService, szPassword = NULL, szKey = NULL, szSid, szRid, szKdc = NULL, szFilename = NULL; PSID sid = NULL, domainSid = NULL; DWORD ret, rid = 0; PDOMAIN_CONTROLLER_INFO cInfo = NULL; kprintf("\n" " .#####. " MIMIKATZ_FULL "\n" " .## ^ ##. \n" " ## / \\ ## /* * *\n" " ## \\ / ## Benjamin DELPY `gentilkiwi` ( [email protected] )\n" " '## v ##' http://blog.gentilkiwi.com (oe.eo)\n" " '#####' ... with thanks to Tom Maddock & Sylvain Monne * * */\n\n"); if(init()) { if(!kull_m_string_args_byName(argc, argv, "ptt", NULL, NULL)) kull_m_string_args_byName(argc, argv, "ticket", &szFilename, TICKET_FILENAME); if(kull_m_string_args_byName(argc, argv, "target", &szTarget, NULL)) { if(kull_m_string_args_byName(argc, argv, "service", &szService, NULL)) { if(kull_m_string_args_byName(argc, argv, "user", &szUser, NULL)) { if(kull_m_string_args_byName(argc, argv, "domain", &szDomain, NULL)) { if(kull_m_string_args_byName(argc, argv, "key", &szKey, NULL) || kull_m_string_args_byName(argc, argv, "password", &szPassword, NULL)) { if(kull_m_string_args_byName(argc, argv, "aes256", NULL, NULL)) userKey.keytype = KERB_ETYPE_AES256_CTS_HMAC_SHA1_96; else if(kull_m_string_args_byName(argc, argv, "aes128", NULL, NULL)) userKey.keytype = KERB_ETYPE_AES128_CTS_HMAC_SHA1_96; else userKey.keytype = KERB_ETYPE_RC4_HMAC_NT; if(NT_SUCCESS(kull_m_kerberos_asn1_helper_util_stringToKey(szUser, szDomain, szPassword, szKey, &userKey))) { if(!kull_m_string_args_byName(argc, argv, "kdc", &szKdc, NULL)) { ret = DsGetDcName(NULL, szDomain, NULL, NULL, DS_IS_DNS_NAME | DS_RETURN_DNS_NAME, &cInfo); if(ret == ERROR_SUCCESS) { szKdc = cInfo->DomainControllerName + 2; kprintf("[KDC] \'%s\' will be the main server\n", szKdc); } else PRINT_ERROR("[KDC] DsGetDcName: %u\n", ret); } if(szKdc) { if(kull_m_string_args_byName(argc, argv, "sid", &szSid, NULL) && kull_m_string_args_byName(argc, argv, "rid", &szRid, NULL)) { if(ConvertStringSidToSid(szSid, &sid)) rid = strtoul(szRid, NULL, 0); else PRINT_ERROR_AUTO("ConvertStringSidToSid"); } if(!(sid && rid)) { if(szPassword) { #pragma warning(push) #pragma warning(disable:4996) impersonateToGetData(szUser, szDomain, szPassword, szKdc,&sid, &rid, _pgmptr); #pragma warning(pop) } else PRINT_ERROR("Impersonate is only supported with a password (you need KDC, SID & RID)\n"); } if(sid && rid) { kprintf("\n" "user : %s\n" "domain : %s\n" "password : %s\n" "sid : " , szUser, szDomain, szKey ? "<NULL>" : "***"); kull_m_string_displaySID(sid); kprintf("\n" "target : %s\n" "service : %s\n" "rid : %u\n" "key : " , szTarget, szService, rid); kull_m_string_printf_hex(userKey.keyvalue.value, userKey.keyvalue.length, 0); kprintf(" (%s)\n" "ticket : %s\n" , kull_m_kerberos_asn1_helper_util_etypeToString(userKey.keytype), szFilename ? szFilename : "** Pass The Ticket **"); if(szKdc) { kprintf("kdc : %s\n\n", szKdc); makeInception(szUser, szDomain, sid, rid, szTarget, szService, &userKey, szKdc, 88, szFilename); } else PRINT_ERROR("No KDC at all\n"); LocalFree(sid); } else PRINT_ERROR("Missing valid SID & RID (argument or auto)\n"); } else PRINT_ERROR("Missing one valid DC (argument or auto)\n"); if(cInfo) NetApiBufferFree(cInfo); LocalFree(userKey.keyvalue.value); } } else PRINT_ERROR("Missing password/key argument\n"); } else PRINT_ERROR("Missing domain argument\n"); } else PRINT_ERROR("Missing user argument\n"); } else PRINT_ERROR("Missing service argument\n"); } else PRINT_ERROR("Missing target argument\n"); } else PRINT_ERROR("init() failed\n"); term(); return 0; }
/* returns 1 on success, 0 on failure */ int Valid_Global_Groups(char *UserName, const char **Groups) { int result = 0; WCHAR wszUserName[UNLEN + 1]; // Unicode user name WCHAR wszDomainControllerName[UNCLEN + 1]; char NTDomain[DNLEN + UNLEN + 2]; char *domain_qualify = NULL; char User[UNLEN + 1]; size_t j; LPGROUP_USERS_INFO_0 pUsrBuf = NULL; LPGROUP_USERS_INFO_0 pTmpBuf; PDOMAIN_CONTROLLER_INFO pDCInfo = NULL; DWORD dwLevel = 0; DWORD dwPrefMaxLen = -1; DWORD dwEntriesRead = 0; DWORD dwTotalEntries = 0; NET_API_STATUS nStatus; DWORD i; DWORD dwTotalCount = 0; LPBYTE pBufTmp = NULL; strncpy(NTDomain, UserName, sizeof(NTDomain)); for (j = 0; j < strlen(NTV_VALID_DOMAIN_SEPARATOR); j++) { if ((domain_qualify = strchr(NTDomain, NTV_VALID_DOMAIN_SEPARATOR[j])) != NULL) break; } if (domain_qualify == NULL) { strcpy(User, NTDomain); strcpy(NTDomain, DefaultDomain); } else { strcpy(User, domain_qualify + 1); domain_qualify[0] = '\0'; strlwr(NTDomain); } debug("Valid_Global_Groups: checking group membership of '%s\\%s'.\n", NTDomain, User); /* Convert ANSI User Name to Unicode */ MultiByteToWideChar(CP_ACP, 0, User, strlen(User) + 1, wszUserName, sizeof(wszUserName) / sizeof(wszUserName[0])); /* Query AD for a DC */ if (DsGetDcName(NULL, NTDomain, NULL, NULL, DS_IS_FLAT_NAME | DS_RETURN_FLAT_NAME, &pDCInfo) != NO_ERROR) { fprintf(stderr, "%s DsGetDcName() failed.'\n", myname); if (pDCInfo != NULL) NetApiBufferFree(pDCInfo); return result; } /* Convert ANSI Domain Controller Name to Unicode */ MultiByteToWideChar(CP_ACP, 0, pDCInfo->DomainControllerName, strlen(pDCInfo->DomainControllerName) + 1, wszDomainControllerName, sizeof(wszDomainControllerName) / sizeof(wszDomainControllerName[0])); debug("Using '%S' as DC for '%s' user's domain.\n", wszDomainControllerName, NTDomain); debug("DC Active Directory Site is %s\n", pDCInfo->DcSiteName); debug("Machine Active Directory Site is %s\n", pDCInfo->ClientSiteName); /* * Call the NetUserGetGroups function * specifying information level 0. */ dwLevel = 0; pBufTmp = NULL; nStatus = NetUserGetGroups(wszDomainControllerName, wszUserName, dwLevel, &pBufTmp, dwPrefMaxLen, &dwEntriesRead, &dwTotalEntries); pUsrBuf = (LPGROUP_USERS_INFO_0) pBufTmp; /* * If the call succeeds, */ if (nStatus == NERR_Success) { if ((pTmpBuf = pUsrBuf) != NULL) { for (i = 0; i < dwEntriesRead; i++) { assert(pTmpBuf != NULL); if (pTmpBuf == NULL) { result = 0; break; } if (wcstrcmparray(pTmpBuf->grui0_name, Groups) == 0) { result = 1; break; } pTmpBuf++; dwTotalCount++; } } } else { result = 0; fprintf(stderr, "%s NetUserGetGroups() failed.'\n", myname); } /* * Free the allocated memory. */ if (pUsrBuf != NULL) NetApiBufferFree(pUsrBuf); if (pDCInfo != NULL) NetApiBufferFree((LPVOID) pDCInfo); return result; }
OperationDomainPaths::OperationDomainPaths(std::queue<std::wstring> & oArgList) : Operation(oArgList) { // exit if there are not enough arguments to parse std::vector<std::wstring> sSubArgs = ProcessAndCheckArgs(1, oArgList); // initialize com only static HRESULT hComInit = CoInitializeEx(NULL, COINIT_MULTITHREADED); if (hComInit != S_OK && hComInit != S_FALSE) { wprintf(L"ERROR: Could not initialize COM.\n"); exit(-1); } // find a domain controller for the specified domain PDOMAIN_CONTROLLER_INFO tDomainControllerInfo; if (DsGetDcName(NULL, sSubArgs[0].c_str(), NULL, NULL, DS_IS_FLAT_NAME | DS_RETURN_DNS_NAME | DS_TRY_NEXTCLOSEST_SITE | DS_FORCE_REDISCOVERY, &tDomainControllerInfo) != ERROR_SUCCESS) { wprintf(L"ERROR: Could not locate domain controller for domain '%s'\n", sSubArgs[0].c_str()); exit(-1); } // create a string std::wstring sPath = std::wstring(L"LDAP://") + (wcsrchr(tDomainControllerInfo->DomainControllerName, '\\') + 1); // grab the dns suffix for later use std::wstring sSuffix = tDomainControllerInfo->DomainName; NetApiBufferFree(tDomainControllerInfo); // bind to global catalog CComPtr<IDirectorySearch> oSearch; if (FAILED(ADsOpenObject(sPath.c_str(), NULL, NULL, ADS_SECURE_AUTHENTICATION, IID_IDirectorySearch, (void**)&oSearch))) { wprintf(L"ERROR: Could not establish search for domain '%s'\n", sSubArgs[0].c_str()); exit(-1); } // setup preferences to search entire tree ADS_SEARCHPREF_INFO SearchPref; SearchPref.dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE; SearchPref.vValue.dwType = ADSTYPE_INTEGER; SearchPref.vValue.Integer = ADS_SCOPE_SUBTREE; // set the search preference. if (FAILED(oSearch->SetSearchPreference(&SearchPref, 1))) { wprintf(L"ERROR: Could not set search preference for domain '%s'\n", sSubArgs[0].c_str()); exit(-1); } // create the search filter WCHAR sSearchFilter[] = L"(&(objectCategory=computer)(|(operatingSystem=*server*)(operatingSystem=*ontap*)(operatingSystem=*netapp*))" \ "(!(userAccountControl:1.2.840.113556.1.4.803:=8192))(!(userAccountControl:1.2.840.113556.1.4.803:=2))(!(msDS-isRODC=true)))"; // execute the search. LPWSTR sAttributes[] = { L"cn" }; ADS_SEARCH_HANDLE hSearch; if (FAILED(oSearch->ExecuteSearch(sSearchFilter, sAttributes, _countof(sAttributes), &hSearch))) { wprintf(L"ERROR: Could not execute search for domain '%s'\n", sSubArgs[0].c_str()); exit(-1); } // enumerate results std::vector<std::wstring> sServers; for (HRESULT hResult = oSearch->GetFirstRow(hSearch); hResult == S_OK; hResult = oSearch->GetNextRow(hSearch)) { // get the data from the column ADS_SEARCH_COLUMN oColumn; if (FAILED(oSearch->GetColumn(hSearch, sAttributes[0], &oColumn)) || oColumn.dwADsType != ADSTYPE_CASE_IGNORE_STRING) { continue; } // add the server to our list oArgList.push(L"/SharePaths"); oArgList.push(std::wstring(oColumn.pADsValues->CaseIgnoreString) + L"." + sSuffix + ((sSubArgs.size() == 2) ? (L":" + sSubArgs[1]) : L"")); // free the column. oSearch->FreeColumn(&oColumn); } // close search handle if (oSearch->CloseSearchHandle(hSearch) != NULL) { wprintf(L"ERROR: Could not close search for domain '%s'\n", sSubArgs[0].c_str()); exit(-1); } };
static auth_result_t do_windows_system_authentication(const char *username, const char *password, char ***pppszUID, char ***pppszGID, char ***pppszGroupNames, int *nGIDs, error_handler_t *error_handler) { auth_result_t ret = JUTI_AUTH_SUCCESS; HANDLE hToken = INVALID_HANDLE_VALUE; int nUIDs = 0; char *domain; char *userbuf; char *user; char *backslash; char *buf = NULL; DWORD buf_size = 0; DOMAIN_CONTROLLER_INFO *pbuf; DWORD dwRes; /* * username can be in format "domain\username", split it up. */ userbuf = strdup(username); user=userbuf; backslash = strchr(user, '\\'); if(backslash != NULL) { domain = user; user = backslash+1; *backslash = '\0'; } else { /* * if no domain was provided, use primary domain by default */ dwRes = DsGetDcName(NULL, NULL, NULL, NULL, DS_RETURN_FLAT_NAME|DS_PDC_REQUIRED, &pbuf); if(dwRes == ERROR_SUCCESS && pbuf->DomainName != NULL) { domain = pbuf->DomainName; } else { /* * no primary domain, use local host as domain */ domain = "."; } } if(!LogonUser( user, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken)) { ret = JUTI_AUTH_ERROR; error_handler->error(MSG_AUTHUSER_WRONG_USER_OR_PASSWORD); goto error; } GetSidStrings(hToken, TokenOwner, pppszUID, NULL, &nUIDs); GetSidStrings(hToken, TokenGroups, pppszGID, pppszGroupNames, nGIDs); CloseHandle(hToken); error: free(userbuf); if(pbuf != NULL) { NetApiBufferFree(pbuf); } return ret; }
LDAPAUTHNT4_API BOOL CUGP(char * userin,char *password,char *machine,char *groupin,int locdom) { { //Handle the command line arguments. LPOLESTR pszBuffer = new OLECHAR[MAX_PATH*2]; LPOLESTR pszBuffer2 = new OLECHAR[MAX_PATH*2]; LPOLESTR pszBuffer3 = new OLECHAR[MAX_PATH*2]; LPOLESTR pszBuffer4 = new OLECHAR[MAX_PATH*2]; mbstowcs( (wchar_t *) pszBuffer, userin, MAX_PATH ); mbstowcs( (wchar_t *) pszBuffer2, password, MAX_PATH ); mbstowcs( (wchar_t *) pszBuffer3, machine, MAX_PATH ); mbstowcs( (wchar_t *) pszBuffer4, groupin, MAX_PATH ); HRESULT hr = S_OK; //Get rootDSE and the domain container's DN. IADs *pObject = NULL; IADs *pObjectUser = NULL; IADs *pObjectGroup = NULL; IDirectorySearch *pDS = NULL; LPOLESTR szPath = new OLECHAR[MAX_PATH]; LPOLESTR myPath = new OLECHAR[MAX_PATH]; VARIANT var; ////////////FIND SERVER NEEDED FOR NT4 DWORD dwRet; PDOMAIN_CONTROLLER_INFO pdci; dwRet = DsGetDcName(NULL, NULL, NULL, NULL , DS_PDC_REQUIRED, &pdci); if (ERROR_SUCCESS!=dwRet) { wprintf(L"PDC not found try a rediscover \n"); dwRet = DsGetDcName(NULL, NULL, NULL, NULL , DS_DIRECTORY_SERVICE_REQUIRED|DS_FORCE_REDISCOVERY, &pdci); if (ERROR_SUCCESS!=dwRet) { wprintf(L"PDC not found \n"); delete [] pszBuffer; delete [] pszBuffer2; delete [] pszBuffer3; delete [] pszBuffer4; delete [] szPath; delete [] myPath; return false; } } ////////////////////////////////////////// wcscpy(szPath,L"LDAP://"); wcscat(szPath,pdci->DomainControllerName+2); wcscat(szPath,L"/rootDSE"); wprintf(szPath); wprintf(L"\n"); hr = ADsOpenObject(szPath, pszBuffer, pszBuffer2, ADS_SECURE_AUTHENTICATION, //Use Secure Authentication IID_IADs, (void**)&pObject); if (FAILED(hr)) { bool result=false; delete [] pszBuffer; delete [] pszBuffer2; delete [] pszBuffer3; delete [] pszBuffer4; delete [] szPath; delete [] myPath; return result; } hr = pObject->Get(L"defaultNamingContext",&var); if (SUCCEEDED(hr)) { wcscpy(szPath,L"LDAP://"); wcscat(szPath,pdci->DomainControllerName+2); wcscat(szPath,L"/"); wcscat(szPath,var.bstrVal); VariantClear(&var); if (pObject) { pObject->Release(); pObject = NULL; } wprintf( szPath); wprintf(L"\n"); //Bind to the root of the current domain. hr = ADsOpenObject(szPath,pszBuffer,pszBuffer2, ADS_SECURE_AUTHENTICATION,IID_IDirectorySearch,(void**)&pDS); if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) { hr = FindUserByName(pDS, pszBuffer, &pObjectUser ); if (FAILED(hr)) { delete [] pszBuffer; delete [] pszBuffer2; delete [] pszBuffer3; delete [] pszBuffer4; delete [] szPath; delete [] myPath; if (pDS) pDS->Release(); if (pObjectUser) pObjectUser->Release(); return false; } if (pObjectUser) pObjectUser->Release(); ///////////////////// VNCACCESS hr = FindGroup(pDS, pszBuffer, &pObjectGroup,pszBuffer4); if (pObjectGroup) { pObjectGroup->Release(); pObjectGroup = NULL; } if (SUCCEEDED(hr)) { wprintf(L"FindGroup OK\n"); IADsGroup * pIADsG; hr = ADsOpenObject( gbsGroup,pszBuffer, pszBuffer2, ADS_SECURE_AUTHENTICATION,IID_IADsGroup, (void**) &pIADsG); if (SUCCEEDED(hr)) { VARIANT_BOOL bMember = FALSE; hr = pIADsG->IsMember(gbsMember,&bMember); if (SUCCEEDED(hr)) { if (bMember == -1) { wprintf(L"Object \n\n%s\n\n IS a member of the following Group:\n\n%s\n\n",gbsMember,gbsGroup); delete [] pszBuffer; delete [] pszBuffer2; delete [] pszBuffer3; delete [] pszBuffer4; delete [] szPath; delete [] myPath; if (pDS) pDS->Release(); return true; } else { BSTR bsMemberGUID = NULL; IDirectoryObject * pDOMember = NULL; hr = ADsOpenObject( gbsMember,pszBuffer, pszBuffer2, ADS_SECURE_AUTHENTICATION,IID_IDirectoryObject, (void**) &pDOMember); if (SUCCEEDED(hr)) { hr = GetObjectGuid(pDOMember,bsMemberGUID); pDOMember->Release(); pDOMember = NULL; if (RecursiveIsMember(pIADsG,bsMemberGUID,gbsMember,true, pszBuffer, pszBuffer2)) { delete [] pszBuffer; delete [] pszBuffer2; delete [] pszBuffer3; delete [] pszBuffer4; delete [] szPath; delete [] myPath; if (pDS) pDS->Release(); return true; } } }//else bmember }//ismember }//iadsgroup }//Findgroup }//user } if (pDS) pDS->Release(); } delete [] pszBuffer; delete [] pszBuffer2; delete [] pszBuffer3; delete [] pszBuffer4; delete [] szPath; delete [] myPath; return false; } return false; }
/* * Class: sun_security_krb5_Credentials * Method: acquireDefaultNativeCreds * Signature: ()Lsun/security/krb5/Credentials; */ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativeCreds( JNIEnv *env, jclass krbcredsClass) { HANDLE LogonHandle = NULL; ULONG PackageId; PKERB_RETRIEVE_TKT_REQUEST CacheRequest = NULL; PKERB_RETRIEVE_TKT_RESPONSE CacheResponse = NULL; ULONG rspSize = 0; DWORD errorCode; NTSTATUS Status,SubStatus; PUCHAR pEncodedTicket = NULL; jobject ticket, clientPrincipal, targetPrincipal, encryptionKey; jobject ticketFlags, startTime, endTime, krbCreds = NULL; jobject authTime, renewTillTime, hostAddresses = NULL; UNICODE_STRING Target = {0}; UNICODE_STRING Target2 = {0}; PDOMAIN_CONTROLLER_INFO DomainControllerInfo = NULL; WCHAR *tgtName = L"krbtgt"; WCHAR *fullName; while (TRUE) { if (krbcredsConstructor == 0) { krbcredsConstructor = (*env)->GetMethodID(env, krbcredsClass, "<init>", "(Lsun/security/krb5/internal/Ticket;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/PrincipalName;Lsun/security/krb5/EncryptionKey;Lsun/security/krb5/internal/TicketFlags;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/KerberosTime;Lsun/security/krb5/internal/HostAddresses;)V"); if (krbcredsConstructor == 0) { printf("Couldn't find com.ibm.security.krb5.Credentials constructor\n"); break; } } //printf("Found KrbCreds constructor\n"); // // Get the logon handle and package ID from the // Kerberos package // if(!PackageConnectLookup(&LogonHandle, &PackageId)) break; #ifdef DEBUG printf("Got handle to Kerberos package\n"); #endif /* DEBUG */ //InitUnicodeString(&Target2, L"krbtgt"); // this doesn't work 'cause I need the domain name too // OK, I don't give up that easily // Go get the current domain name errorCode = DsGetDcName( (LPCTSTR) NULL, // machine name (LPCTSTR) NULL, // DomainName, if NULL, I'm asking what it is (GUID *) NULL, // DomainGuid, (LPCTSTR) NULL, // SiteName, DS_GC_SERVER_REQUIRED, //Flags &DomainControllerInfo); if (errorCode != NO_ERROR) { printf("DsGetDcName returned %d\n", errorCode); break; } #ifdef DEBUG printf("The domain name is %S\n", DomainControllerInfo->DomainName); #endif /* DEBUG */ // Build a fully-qualified name fullName = (WCHAR *) LocalAlloc(LMEM_ZEROINIT,((wcslen(tgtName)+wcslen(L"/")+wcslen(DomainControllerInfo->DomainName)) * sizeof(WCHAR) + sizeof(UNICODE_NULL))); wcscat(fullName, tgtName); wcscat(fullName, L"/"); wcscat(fullName, DomainControllerInfo->DomainName); #ifdef DEBUG printf("The fully-qualified name is %S\n", fullName); #endif /* DEBUG */ InitUnicodeString(&Target2, fullName); CacheRequest = (PKERB_RETRIEVE_TKT_REQUEST) LocalAlloc(LMEM_ZEROINIT, Target2.Length + sizeof(KERB_RETRIEVE_TKT_REQUEST)); CacheRequest->MessageType = KerbRetrieveEncodedTicketMessage ; Target.Buffer = (LPWSTR) (CacheRequest + 1); Target.Length = Target2.Length; Target.MaximumLength = Target2.MaximumLength; CopyMemory( Target.Buffer, Target2.Buffer, Target2.Length ); CacheRequest->TargetName = Target; CacheRequest->EncryptionType = KERB_ETYPE_DES_CBC_MD5; // mdu Status = LsaCallAuthenticationPackage( LogonHandle, PackageId, CacheRequest, Target2.Length + sizeof(KERB_RETRIEVE_TKT_REQUEST), (PVOID *) &CacheResponse, &rspSize, &SubStatus ); #ifdef DEBUG printf("Response size is %d\n", rspSize); #endif /* DEBUG */ LocalFree(fullName); if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) { if (!LSA_SUCCESS(Status)) { ShowNTError("LsaCallAuthenticationPackage", Status); } else { ShowNTError("Protocol status", SubStatus); } break; } // Now we need to skip over most of the junk in the buffer to get to the ticket // Here's what we're looking at... /* typedef struct _KERB_RETRIEVE_TKT_RESPONSE { KERB_EXTERNAL_TICKET Ticket; } KERB_RETRIEVE_TKT_RESPONSE, *PKERB_RETRIEVE_TKT_RESPONSE; typedef struct _KERB_EXTERNAL_TICKET { PKERB_EXTERNAL_NAME ServiceName; PKERB_EXTERNAL_NAME TargetName; PKERB_EXTERNAL_NAME ClientName; UNICODE_STRING DomainName; UNICODE_STRING TargetDomainName; UNICODE_STRING AltTargetDomainName; KERB_CRYPTO_KEY SessionKey; ULONG TicketFlags; ULONG Flags; LARGE_INTEGER KeyExpirationTime; LARGE_INTEGER StartTime; LARGE_INTEGER EndTime; LARGE_INTEGER RenewUntil; LARGE_INTEGER TimeSkew; ULONG EncodedTicketSize; PUCHAR EncodedTicket; <========== Here's the good stuff } KERB_EXTERNAL_TICKET, *PKERB_EXTERNAL_TICKET; typedef struct _KERB_EXTERNAL_NAME { SHORT NameType; USHORT NameCount; UNICODE_STRING Names[ANYSIZE_ARRAY]; } KERB_EXTERNAL_NAME, *PKERB_EXTERNAL_NAME; typedef struct _LSA_UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } LSA_UNICODE_STRING, *PLSA_UNICODE_STRING; typedef LSA_UNICODE_STRING UNICODE_STRING, *PUNICODE_STRING; typedef struct KERB_CRYPTO_KEY { LONG KeyType; ULONG Length; PUCHAR Value; } KERB_CRYPTO_KEY, *PKERB_CRYPTO_KEY; */ // Build a com.ibm.security.krb5.Ticket ticket = BuildTicket(env, CacheResponse->Ticket.EncodedTicket, CacheResponse->Ticket.EncodedTicketSize); if (ticket == NULL) { break; } // OK, have a Ticket, now need to get the client name clientPrincipal = BuildClientPrincipal(env, CacheResponse->Ticket.ClientName); // mdu if (clientPrincipal == NULL) break; // and the "name" of tgt targetPrincipal = BuildTGSPrincipal(env, CacheResponse->Ticket.TargetDomainName); // mdu if (targetPrincipal == NULL) break; // Get the encryption key encryptionKey = BuildEncryptionKey(env, &(CacheResponse->Ticket.SessionKey)); if (encryptionKey == NULL) break; // and the ticket flags ticketFlags = BuildTicketFlags(env, &(CacheResponse->Ticket.TicketFlags)); if (ticketFlags == NULL) break; // Get the start time startTime = BuildKerberosTime(env, &(CacheResponse->Ticket.StartTime)); if (startTime == NULL) break; /* * mdu: No point storing the eky expiration time in the auth * time field. Set it to be same as startTime. Looks like * windows does not have post-dated tickets. */ authTime = startTime; // and the end time endTime = BuildKerberosTime(env, &(CacheResponse->Ticket.EndTime)); if (endTime == NULL) break; // Get the renew till time renewTillTime = BuildKerberosTime(env, &(CacheResponse->Ticket.RenewUntil)); if (renewTillTime == NULL) break; // and now go build a KrbCreds object krbCreds = (*env)->NewObject( env, krbcredsClass, krbcredsConstructor, ticket, clientPrincipal, targetPrincipal, encryptionKey, ticketFlags, authTime, // mdu startTime, endTime, renewTillTime, //mdu hostAddresses); break; } // end of WHILE if (DomainControllerInfo != NULL) { NetApiBufferFree(DomainControllerInfo); } if (CacheResponse != NULL) { LsaFreeReturnBuffer(CacheResponse); } if (CacheRequest) { LocalFree(CacheRequest); } return krbCreds; }