Пример #1
0
// mdu
jobject BuildTGSPrincipal(JNIEnv *env, 
			  UNICODE_STRING domainName) {
	jobject principal = NULL, stringArray;
	jstring tempString;
	int nameCount;
	PUNICODE_STRING scanner;
        UNICODE_STRING KRBTGT = {0};
	InitUnicodeString(&KRBTGT, L"krbtgt");

	stringArray = (*env)->NewObjectArray(env, 2, 
					     javaLangStringClass, NULL);

	if (stringArray == NULL) {
		printf("Can't allocate String array for TGS Principal\n");
		return principal;
	}

	// OK, got a Char array, so construct a String

	scanner = &KRBTGT;
	tempString = (*env)->NewString(env, 
				       (const jchar*)scanner->Buffer, 
				       scanner->Length/sizeof(WCHAR));

	// Set the String into the StringArray
	(*env)->SetObjectArrayElement(env, stringArray, 0, tempString);		
	// Do I have to worry about storage reclamation here?

	// OK, got a Char array, so construct a String
	scanner = &domainName; // The unicode domain name
	tempString = (*env)->NewString(env, 
				       (const jchar*)scanner->Buffer, 
				       scanner->Length/sizeof(WCHAR));

	// Set the String into the StringArray
	(*env)->SetObjectArrayElement(env, stringArray, 1, tempString);		
	// Do I have to worry about storage reclamation here?

	principal = (*env)->NewObject(env, principalNameClass, 
				      principalNameConstructor, stringArray);

	return principal;
}
Пример #2
0
DWORD 
GetEncodedTicket(
    HANDLE LogonHandle,
    ULONG PackageId,
    wchar_t *Server
    )
{
    NTSTATUS Status;
    PKERB_RETRIEVE_TKT_REQUEST CacheRequest = NULL;
    PKERB_RETRIEVE_TKT_RESPONSE CacheResponse = NULL;
    PKERB_EXTERNAL_TICKET Ticket;
    ULONG ResponseSize;
    NTSTATUS SubStatus;
    BOOLEAN Trusted = TRUE;
    BOOLEAN Success = FALSE;
    UNICODE_STRING Target = {0}; 
    UNICODE_STRING Target2 = {0};

    InitUnicodeString( &Target2, Server);

    CacheRequest = (PKERB_RETRIEVE_TKT_REQUEST)
            LocalAlloc(LMEM_ZEROINIT, Target2.Length + sizeof(KERB_RETRIEVE_TKT_REQUEST));

    CacheRequest->MessageType = KerbRetrieveEncodedTicketMessage ;
    CacheRequest->LogonId.LowPart = 0;
    CacheRequest->LogonId.HighPart = 0;

 
    Target.Buffer = (LPWSTR) (CacheRequest + 1);
    Target.Length = Target2.Length;
    Target.MaximumLength = Target2.MaximumLength;

    CopyMemory(
        Target.Buffer,
        Target2.Buffer,
        Target2.Length
        );

    CacheRequest->TargetName = Target;

    Status = LsaCallAuthenticationPackage(
                LogonHandle,
                PackageId,
                CacheRequest,
                Target2.Length + sizeof(KERB_RETRIEVE_TKT_REQUEST),
                (PVOID *) &CacheResponse,
                &ResponseSize,
                &SubStatus
                );

    if (!SEC_SUCCESS(Status) || !SEC_SUCCESS(SubStatus))
    {
        ShowNTError("LsaCallAuthenticationPackage", Status);
        printf("Substatus: 0x%x\n",SubStatus);
        ShowNTError("Substatus:", SubStatus);

    }
    else
    {
        Ticket = &(CacheResponse->Ticket);

        printf("\nEncoded Ticket:\n\n");

        printf("ServiceName: "); PrintKerbName(Ticket->ServiceName);

        printf("TargetName: "); PrintKerbName(Ticket->TargetName);

        printf("ClientName: "); PrintKerbName(Ticket->ClientName);
        
        printf("DomainName: %.*S\n",
            Ticket->DomainName.Length/sizeof(WCHAR),Ticket->DomainName.Buffer);

        printf("TargetDomainName: %.*S\n",
            Ticket->TargetDomainName.Length/sizeof(WCHAR),Ticket->TargetDomainName.Buffer);

        printf("AltTargetDomainName: %.*S\n",
            Ticket->AltTargetDomainName.Length/sizeof(WCHAR),Ticket->AltTargetDomainName.Buffer);

        printf("TicketFlags: (0x%x) ",Ticket->TicketFlags);
        PrintTktFlags(Ticket->TicketFlags);
        PrintTime("KeyExpirationTime: ",Ticket->KeyExpirationTime);
        PrintTime("StartTime: ",Ticket->StartTime);
        PrintTime("EndTime: ",Ticket->EndTime);
        PrintTime("RenewUntil: ",Ticket->RenewUntil);
        PrintTime("TimeSkew: ",Ticket->TimeSkew);
        PrintEType(Ticket->SessionKey.KeyType);

        Success = TRUE;
        
    }

    if (CacheResponse)
    {
        LsaFreeReturnBuffer(CacheResponse);
    }
    if (CacheRequest)
    {
        LocalFree(CacheRequest);
    }

    return Success;
}
Пример #3
0
int _tmain(int argc, TCHAR *argv[])
{
   BOOL bResult;
   NTSTATUS Status;
   NTSTATUS SubStatus;

   HANDLE hLsa = NULL;
   HANDLE hProcess = NULL;
   HANDLE hToken = NULL;
   HANDLE hTokenS4U = NULL;

   LSA_STRING Msv1_0Name = { 0 };
   LSA_STRING OriginName = { 0 };
   PMSV1_0_S4U_LOGON pS4uLogon = NULL;
   TOKEN_SOURCE TokenSource;
   ULONG ulAuthenticationPackage;
   DWORD dwMessageLength;

   PBYTE pbPosition;

   PROCESS_INFORMATION pi = { 0 };
   STARTUPINFO si = { 0 };

   PTOKEN_GROUPS pGroups = NULL;
   PSID pLogonSid = NULL;
   PSID pExtraSid = NULL;

   PVOID pvProfile = NULL;
   DWORD dwProfile = 0;
   LUID logonId = { 0 };
   QUOTA_LIMITS quotaLimits;

   LPTSTR szCommandLine = NULL;
   LPTSTR szSrcCommandLine = TEXT("%systemroot%\\system32\\cmd.exe");
   LPTSTR szDomain = NULL;
   LPTSTR szUsername = NULL;
   TCHAR seps[] = TEXT("\\");
   TCHAR *next_token = NULL;

   g_hHeap = GetProcessHeap();

   if (argc < 2)
   {
      fprintf(stderr, "Usage:\n   s4u.exe Domain\\Username [Extra SID]\n\n");
      goto End;
   }

   //
   // Get DOMAIN and USERNAME from command line.
   //
   szDomain = _tcstok_s(argv[1], seps, &next_token);
   if (szDomain == NULL)
   {
      fprintf(stderr, "Unable to parse command line.\n");
      goto End;
   }

   szUsername = _tcstok_s(NULL, seps, &next_token);
   if (szUsername == NULL)
   {
      fprintf(stderr, "Unable to parse command line.\n");
      goto End;
   }

   //
   // Activate the TCB privilege
   //
   hProcess = GetCurrentProcess();
   OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
   if (!SetPrivilege(hToken, SE_TCB_NAME, TRUE))
   {
      goto End;
   }

   //
   // Get logon SID
   //
   if (!GetLogonSID(hToken, &pLogonSid))
   {
      fprintf(stderr, "Unable to find logon SID.\n");
      goto End;
   }

   //
   // Connect (Untrusted) to LSA
   //
   Status = LsaConnectUntrusted(&hLsa);
   if (Status!=STATUS_SUCCESS)
   {
      fprintf(stderr, "LsaConnectUntrusted failed (error 0x%x).", Status);
      hLsa = NULL;
      goto End;
   }

   //
   // Lookup for the MSV1_0 authentication package (NTLMSSP)
   //
   InitLsaString(&Msv1_0Name, MSV1_0_PACKAGE_NAME);
   Status = LsaLookupAuthenticationPackage(hLsa, &Msv1_0Name, &ulAuthenticationPackage);
   if (Status!=STATUS_SUCCESS)
   {
      fprintf(stderr, "LsaLookupAuthenticationPackage failed (error 0x%x).", Status);
      hLsa = NULL;
      goto End;
   }

   //
   // Create MSV1_0_S4U_LOGON structure
   //
   dwMessageLength = sizeof(MSV1_0_S4U_LOGON) + (2 + wcslen(szDomain) + wcslen(szUsername)) * sizeof(WCHAR);
   pS4uLogon = (PMSV1_0_S4U_LOGON)HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, dwMessageLength);
   if (pS4uLogon == NULL)
   {
      fprintf(stderr, "HeapAlloc failed (error %u).", GetLastError());
      goto End;
   }

   pS4uLogon->MessageType = MsV1_0S4ULogon;
   pbPosition = (PBYTE)pS4uLogon + sizeof(MSV1_0_S4U_LOGON);
   pbPosition = InitUnicodeString(&pS4uLogon->UserPrincipalName, szUsername, pbPosition);
   pbPosition = InitUnicodeString(&pS4uLogon->DomainName, szDomain, pbPosition);

   //
   // Misc
   //
   strcpy_s(TokenSource.SourceName, TOKEN_SOURCE_LENGTH, "S4UWin");
   InitLsaString(&OriginName, "S4U for Windows");
   AllocateLocallyUniqueId(&TokenSource.SourceIdentifier);

   //
   // Add extra SID to token.
   //
   // If the application needs to connect to a Windows Desktop, Logon SID must be added to the Token.
   //
   pGroups = (PTOKEN_GROUPS)HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, sizeof(TOKEN_GROUPS) + 2*sizeof(SID_AND_ATTRIBUTES));
   if (pGroups == NULL)
   {
      fprintf(stderr, "HeapAlloc failed (error %u).", GetLastError());
      goto End;
   }

   pGroups->GroupCount = 1;
   pGroups->Groups[0].Attributes = SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
   pGroups->Groups[0].Sid = pLogonSid;

   //
   // If an extra SID is specified to command line, add it to the pGroups structure.
   //
   if (argc==3)
   {
      bResult = ConvertStringSidToSid(argv[2], &pExtraSid);

      if (bResult == TRUE)
      {
         pGroups->GroupCount = 2;
         pGroups->Groups[1].Attributes = SE_GROUP_ENABLED | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_MANDATORY;
         pGroups->Groups[1].Sid = pExtraSid;
      }
      else
      {
         fprintf(stderr, "Unable to convert SID (error %u).", GetLastError());
      }
   }

   //
   // Call LSA
   //
   Status = LsaLogonUser(
      hLsa,
      &OriginName,
      Network,                // Or Batch
      ulAuthenticationPackage,
      pS4uLogon,
      dwMessageLength,
      pGroups,                // LocalGroups
      &TokenSource,           // SourceContext
      &pvProfile,
      &dwProfile,
      &logonId,
      &hTokenS4U,
      &quotaLimits,
      &SubStatus
      );
   if (Status!=STATUS_SUCCESS)
   {
      printf("LsaLogonUser failed (error 0x%x).\n", Status);
      goto End;
   }

   printf("LsaLogonUser: OK, LogonId: 0x%x-0x%x\n", logonId.HighPart, logonId.LowPart);

   //
   // Create process with S4U token.
   //
   si.cb = sizeof(STARTUPINFO);
   si.lpDesktop = TEXT("winsta0\\default");

   //
   // Warning: szCommandLine parameter of CreateProcessAsUser() must be writable
   //
   szCommandLine = (LPTSTR)HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, MAX_PATH * sizeof(TCHAR));
   if (szCommandLine == NULL)
   {
      fprintf(stderr, "HeapAlloc failed (error %u).", GetLastError());
      goto End;
   }

   if (ExpandEnvironmentStrings(szSrcCommandLine, szCommandLine, MAX_PATH) == 0)
   {
      fprintf(stderr, "ExpandEnvironmentStrings failed (error %u).", GetLastError());
      goto End;
   }

   //
   // CreateProcessAsUser required SeAssignPrimaryTokenPrivilege but no need to be activated.
   //
   bResult = CreateProcessAsUser(
      hTokenS4U,
      NULL,
      szCommandLine,
      NULL,
      NULL,
      FALSE,
      NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
      NULL,
      TEXT("c:\\"),
      &si,
      &pi
      );
   if (bResult == FALSE)
   {
      printf("CreateProcessAsUser failed (error %u).\n", GetLastError());
      goto End;
   }

End:
   //
   // Free resources
   //
   if (Msv1_0Name.Buffer)
      HeapFree(g_hHeap, 0, Msv1_0Name.Buffer);
   if (OriginName.Buffer)
      HeapFree(g_hHeap, 0, OriginName.Buffer);
   if (pLogonSid)
      HeapFree(g_hHeap, 0, pLogonSid);
   if (pExtraSid)
      LocalFree(pExtraSid);
   if (pS4uLogon)
      HeapFree(g_hHeap, 0, pS4uLogon);
   if (pGroups)
      HeapFree(g_hHeap, 0, pGroups);
   if (pvProfile)
      LsaFreeReturnBuffer(pvProfile);
   if (hLsa)
      LsaClose(hLsa);
   if (hToken)
      CloseHandle(hToken);
   if (hTokenS4U)
      CloseHandle(hTokenS4U);
   if (pi.hProcess)
      CloseHandle(pi.hProcess);
   if (pi.hThread)
      CloseHandle(pi.hThread);

   return EXIT_SUCCESS;
}
Пример #4
0
/*
 * 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;
}