/* * sspdebug.cpp * MSUAM * * Created by mconrad on Sun Sep 30 2001. * Copyright (c) 2001 Microsoft Corp. All rights reserved. * */ #ifdef SSP_TARGET_CARBON #include #endif #include #include #include #include //windows version #include #if defined(SSP_DEBUG) && defined(SSP_TARGET_CARBON) // // Valid values of NegotiateFlags // typedef struct _NTLM_NEG_FLAGS { char* desc; ULONG flag; } NTLM_NEG_FLAGS; NTLM_NEG_FLAGS g_flagTable[] = { // // Valid values of NegotiateFlags // {"NTLMSSP_NEGOTIATE_UNICODE", 0x00000001 }, // Text strings are in unicode {"NTLMSSP_NEGOTIATE_OEM", 0x00000002 }, // Text strings are in OEM {"NTLMSSP_REQUEST_TARGET", 0x00000004 }, // Server should return its authentication realm {"NTLMSSP_NEGOTIATE_SIGN", 0x00000010 }, // Request signature capability {"NTLMSSP_NEGOTIATE_SEAL", 0x00000020 }, // Request confidentiality {"NTLMSSP_NEGOTIATE_DATAGRAM", 0x00000040 }, // Use datagram style authentication {"NTLMSSP_NEGOTIATE_LM_KEY", 0x00000080 }, // Use LM session key for sign/seal {"NTLMSSP_NEGOTIATE_NETWARE", 0x00000100 }, // NetWare authentication {"NTLMSSP_NEGOTIATE_NTLM", 0x00000200 }, // NTLM authentication {"NTLMSSP_NEGOTIATE_NT_ONLY", 0x00000400 }, // NT authentication only (no LM) {"NTLMSSP_NEGOTIATE_NULL_SESSION", 0x00000800 }, // NULL Sessions on NT 5.0 and beyand {"NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED", 0x1000 }, // Domain Name supplied on negotiate {"NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED", 0x2000 }, // Workstation Name supplied on negotiate {"NTLMSSP_NEGOTIATE_LOCAL_CALL", 0x00004000}, // Indicates client/server are same machine {"NTLMSSP_NEGOTIATE_ALWAYS_SIGN", 0x00008000}, // Sign for all security levels // // Valid target types returned by the server in Negotiate Flags // {"NTLMSSP_TARGET_TYPE_DOMAIN", 0x00010000}, // TargetName is a domain name {"NTLMSSP_TARGET_TYPE_SERVER", 0x00020000}, // TargetName is a server name {"NTLMSSP_TARGET_TYPE_SHARE", 0x00040000}, // TargetName is a share name {"NTLMSSP_NEGOTIATE_NTLM2", 0x00080000}, // NTLM2 authentication added for NT4-SP4 {"NTLMSSP_NEGOTIATE_IDENTIFY", 0x00100000}, // Create identify level token // // Valid requests for additional output buffers // {"NTLMSSP_REQUEST_INIT_RESPONSE", 0x00100000}, // get back session keys {"NTLMSSP_REQUEST_ACCEPT_RESPONSE", 0x00200000}, // get back session key, LUID {"NTLMSSP_REQUEST_NON_NT_SESSION_KEY", 0x00400000}, // request non-nt session key {"NTLMSSP_NEGOTIATE_TARGET_INFO", 0x00800000}, // target info present in challenge message {"NTLMSSP_NEGOTIATE_EXPORTED_CONTEXT", 0x01000000}, // It's an exported context {"NTLMSSP_NEGOTIATE_128", 0x20000000}, // negotiate 128 bit encryption {"NTLMSSP_NEGOTIATE_KEY_EXCH", 0x40000000}, // exchange a key using key exchange key {"NTLMSSP_NEGOTIATE_56", 0x80000000}, // negotiate 56 bit encryption // // flags used in client space to control sign and seal; never appear on the wire // {"NTLMSSP_APP_SEQ", 0x0040}, // Use application provided seq num }; char toChar(IN char c) { if (c >= 0x20 && c <= 0x7E) { return c; } return '.'; } void spaceIt(IN char* buf, IN ULONG len) { ULONG i; for ( i = 0; i < len; i++) { buf[i] = ' '; } } char toHex(IN int c) { if (c >= 0x0 && c <= 0x9) { return c + '0'; } return c - 10 + 'a'; } void _SspDebugPrintHex(IN const void *buffer, IN LONG len) { unsigned char* p = (unsigned char*) buffer; int high = 0; int low = 0; char line[256] = {0}; int i; if (!len) return; spaceIt(line, 72); for (i = 0; i < len; i++) { high = p[i] / 16; low = p[i] % 16; line[3 * (i % 16)] = toHex(high); line[3 * (i % 16) + 1] = toHex(low); line [52 + (i % 16)] = toChar(p[i]); if (i % 16 == 7 && i != (len - 1)) { line[3 * (i % 16) + 2] = '-'; } if (i % 16 == 15) { printf(" %s\n", line); spaceIt(line, 72); } } printf(" %s\n", line); } void _SspDebugPrintString32(IN STRING32 str32, IN const void* base) { // printf("%d(%d):", str32.Length, str32.MaximumLength); if (str32.Length <= 1024) { _SspDebugPrintHex((const char*)base + (ULONG)str32.Buffer, str32.Length); } else { printf(" Length %d, MaximumLenght %d ", str32.Length, str32.MaximumLength); printf(" \n"); } } PCSTR g_attr_table[] = { "", "NetbiosServerName", "NetbiosDomainName", "DnsComputerName", "DnsDomainName", "DnsTreeName", "Flags", "", "", "", "", "", "", }; void _SspDebugPrintString32TargetInfo(IN STRING32* pTargetInfo, IN const void* buffer) { const char* start = reinterpret_cast(buffer) + pTargetInfo->Buffer; const char* p = NULL; USHORT attr = 0; USHORT len = 0; if (pTargetInfo->Length >= 1024) { printf("String32 TargetInfo too large\n"); return; } _SspDebugPrintHex(start, pTargetInfo->Length); for (p = start; p < start + pTargetInfo->Length; p += (2 * sizeof(USHORT) + len)){ attr = reinterpret_cast(const_cast(p))[0]; len = reinterpret_cast(const_cast(p))[1]; if (attr >= MsvAvNbComputerName && attr <= MsvAvDnsTreeName) { printf("%s: ", g_attr_table[attr]); //debugNPrintfW(p + 2 * sizeof(USHORT), len); printf("\n"); } else if (attr == MsvAvFlags) { printf("Flags: 0x%x\n", (unsigned int)*reinterpret_cast(const_cast(p + 2 * sizeof(USHORT))) ); } else if (attr == MsvAvEOL) { break; } else { printf("Unrecognized attribute %d\n", attr); } } } void _SspDebugPrintNegFlags(IN ULONG flags) { unsigned int i; printf(" 0x%x\n", (unsigned int)flags); for (i = 0; i < sizeof(g_flagTable)/sizeof(*g_flagTable); i++) { if (g_flagTable[i].flag & flags) { flags &= ~g_flagTable[i].flag; printf(" + %s\n", g_flagTable[i].desc); } } if (flags) { printf("unrecognized flags: 0x%x\n", (unsigned int)flags); } } void _SspDebugPrintNTLMMsg(IN const void* buf, IN ULONG len) { const char* buffer = reinterpret_cast(buf); NTLM_MESSAGE_TYPE msgType; ULONG negFlags; NEGOTIATE_MESSAGE* pNeg = (NEGOTIATE_MESSAGE*) buffer; CHALLENGE_MESSAGE* pCha = (CHALLENGE_MESSAGE*) buffer; AUTHENTICATE_MESSAGE* pAut = (AUTHENTICATE_MESSAGE*) buffer; STRING32 scratch = {0}; printf("buf %p, len %d\n", buf, (unsigned int)len); if (!buf) { printf("****Empty NTLM msg\n"); return; } if (strcmp(buffer, "NTLMSSP")) { printf("****buffer corrupted!\n"); return; } printf("******************* Message Begin *********************\n"); _SspDebugPrintHex(buffer,len); printf("******************* Message END ***********************\n"); msgType = *((NTLM_MESSAGE_TYPE*) (buffer + strlen(buffer) + 1)); switch (msgType) { case NtLmNegotiate: printf("Msg type: Negociate\n"); printf("NegotiateFlags: "); _SspDebugPrintNegFlags(pNeg->NegotiateFlags); printf("OemDomainName: \n"); _SspDebugPrintString32(pNeg->OemDomainName, buffer); printf("OemWorkstationName: \n"); _SspDebugPrintString32(pNeg->OemWorkstationName, buffer); break; case NtLmChallenge: printf("Msg type: Challenge\n"); printf("TargeName: \n"); _SspDebugPrintString32(pCha->TargetName, buffer); printf("NegotiateFlags: "); _SspDebugPrintNegFlags(pCha->NegotiateFlags); printf("Chanllenge: \n"); _SspDebugPrintHex(pCha->Challenge, MSV1_0_CHALLENGE_LENGTH); printf("ServerContextHandle (Lower Upper): \n"); _SspDebugPrintHex(&pCha->ServerContextHandle, sizeof(pCha->ServerContextHandle)); printf("TargetInfo: \n"); _SspDebugPrintString32TargetInfo(&pCha->TargetInfo, buffer); break; case NtLmAuthenticate: printf("Msg type: Authenticate\n"); memcpy(&scratch, &pAut->LmChallengeResponse, sizeof(scratch)); SspSwapString32Bytes(&scratch); printf("LmChallengeResponse (length %d): \n", scratch.Length); _SspDebugPrintHex(buffer + (ULONG) scratch.Buffer, scratch.Length); memcpy(&scratch, &pAut->NtChallengeResponse, sizeof(scratch)); SspSwapString32Bytes(&scratch); printf("NtChallengeResponse (length %d): \n", scratch.Length); _SspDebugPrintHex(buffer + (ULONG) scratch.Buffer, scratch.Length); printf("DomainName: \n"); memcpy(&scratch, &pAut->DomainName, sizeof(scratch)); SspSwapString32Bytes(&scratch); _SspDebugPrintString32(scratch, buffer); printf("UserName: \n"); memcpy(&scratch, &pAut->UserName, sizeof(scratch)); SspSwapString32Bytes(&scratch); _SspDebugPrintString32(scratch, buffer); printf("Workstation: \n"); memcpy(&scratch, &pAut->Workstation, sizeof(scratch)); SspSwapString32Bytes(&scratch); _SspDebugPrintString32(scratch, buffer); memcpy(&scratch, &pAut->SessionKey, sizeof(scratch)); SspSwapString32Bytes(&scratch); printf("Sessionkey (length %d): \n", scratch.Length); _SspDebugPrintHex(buffer + (ULONG) scratch.Buffer, scratch.Length); printf("NegotiateFlags: "); negFlags = pAut->NegotiateFlags; swaplong(negFlags); _SspDebugPrintNegFlags(negFlags); break; case NtLmUnknown: printf("unknown msg.\n"); break; default: printf("buffer corrupted.\n"); break; } printf("******************** INTERP END ***********************\n"); } #endif //SSP_DEBUG