diff --git a/FiddlerImportNetlog/Importer.cs b/FiddlerImportNetlog/Importer.cs index cd862bf..6a8e989 100644 --- a/FiddlerImportNetlog/Importer.cs +++ b/FiddlerImportNetlog/Importer.cs @@ -233,7 +233,7 @@ public bool ExtractSessionsFromJSON(Hashtable htFile) int iEvent = -1; int iLastPct = 25; var dictURLRequests = new Dictionary>(); - var dictSockets = new Dictionary>(); + var dictSecureSockets = new Dictionary>(); // Loop over events; bucket those associated to URLRequests by the source request's ID. ArrayList alEvents = htFile["events"] as ArrayList; @@ -261,14 +261,14 @@ public bool ExtractSessionsFromJSON(Hashtable htFile) iType != NetLogMagics.SSL_HANDSHAKE_MESSAGE_RECEIVED) continue; // Get (or create) the List of entries for this SOCKET. - if (!dictSockets.ContainsKey(iSocketID)) + if (!dictSecureSockets.ContainsKey(iSocketID)) { events = new List(); - dictSockets.Add(iSocketID, events); + dictSecureSockets.Add(iSocketID, events); } else { - events = dictSockets[iSocketID]; + events = dictSecureSockets[iSocketID]; } // Add this event to the SOCKET's list. events.Add(htEvent); @@ -328,7 +328,7 @@ public bool ExtractSessionsFromJSON(Hashtable htFile) sessSummary.utilSetResponseBody(sbClientInfo.ToString()); GenerateDebugTreeSession(dictURLRequests); - GenerateSocketListSession(dictSockets); + GenerateSocketListSession(dictSecureSockets); NotifyProgress(1, "Import Completed."); return true; @@ -383,14 +383,17 @@ private void GenerateDebugTreeSession(Dictionary> dictURLRe htDebug.Add(kvpURLRequest.Key, alE); } - _listSessions.Add(Session.BuildFromData(false, - new HTTPRequestHeaders( - String.Format("/URL_REQUESTS"), // TODO: Add Machine name? - new[] { "Host: NETLOG" }), - Utilities.emptyByteArray, - new HTTPResponseHeaders(200, "Analyzed Data", new[] { "Content-Type: application/json; charset=utf-8" }), - Encoding.UTF8.GetBytes(JSON.JsonEncode(htDebug)), - SessionFlags.ImportedFromOtherTool | SessionFlags.RequestGeneratedByFiddler | SessionFlags.ResponseGeneratedByFiddler | SessionFlags.ServedFromCache)); + if (htDebug.Count > 0) + { + _listSessions.Add(Session.BuildFromData(false, + new HTTPRequestHeaders( + String.Format("/URL_REQUESTS"), // TODO: Add Machine name? + new[] { "Host: NETLOG" }), + Utilities.emptyByteArray, + new HTTPResponseHeaders(200, "Analyzed Data", new[] { "Content-Type: application/json; charset=utf-8" }), + Encoding.UTF8.GetBytes(JSON.JsonEncode(htDebug)), + SessionFlags.ImportedFromOtherTool | SessionFlags.RequestGeneratedByFiddler | SessionFlags.ResponseGeneratedByFiddler | SessionFlags.ServedFromCache)); + } } catch (Exception e) { FiddlerApplication.Log.LogFormat("GenerateDebugTreeSession failed: "+ DescribeExceptionWithStack(e)); } } @@ -402,8 +405,8 @@ private void GenerateSocketListSession(Dictionary> dictSock Hashtable htAllSockets = new Hashtable(); foreach (KeyValuePair> kvpSocket in dictSockets) { + string sSubjectCNinFirstCert = String.Empty; Hashtable htThisSocket = new Hashtable(); - htAllSockets.Add(kvpSocket.Key, htThisSocket); foreach (Hashtable htEvent in kvpSocket.Value) { @@ -415,6 +418,18 @@ private void GenerateSocketListSession(Dictionary> dictSock StringBuilder sbCertsReceived = new StringBuilder(); ArrayList alCerts = htParams["certificates"] as ArrayList; + // Try to promote the SubjectCN to the title of this node + try + { + if (String.IsNullOrEmpty(sSubjectCNinFirstCert) && alCerts.Count > 0) + { + var FirstCert = new X509Certificate2(); + string sCertInfo = alCerts[0] as string; + FirstCert.Import(Encoding.ASCII.GetBytes(sCertInfo)); + sSubjectCNinFirstCert = (" - " + FirstCert.GetNameInfo(X509NameType.SimpleName, false)).ToLower(); + } + } + catch { } htThisSocket.Add("Server Certificates", alCerts); continue; } @@ -424,7 +439,8 @@ private void GenerateSocketListSession(Dictionary> dictSock if (iType == NetLogMagics.SSL_HANDSHAKE_MESSAGE_RECEIVED) { int iHandshakeMessageType = (int)(double)htParams["type"]; - if (iHandshakeMessageType != 13) continue; + + if (iHandshakeMessageType != 13/*CertificateRequest*/) continue; // Okay, it's a CertificateRequest. Log it. string sBase64Bytes = htParams["bytes"] as string; @@ -515,16 +531,25 @@ private void GenerateSocketListSession(Dictionary> dictSock continue; } } + + if (htThisSocket.Count > 0) + { + htAllSockets.Add(kvpSocket.Key + sSubjectCNinFirstCert, htThisSocket); + } } - _listSessions.Add(Session.BuildFromData(false, - new HTTPRequestHeaders( - String.Format("/SECURE_SOCKETS"), // TODO: Add Machine name? - new[] { "Host: NETLOG" }), - Utilities.emptyByteArray, - new HTTPResponseHeaders(200, "Analyzed Data", new[] { "Content-Type: application/json; charset=utf-8" }), - Encoding.UTF8.GetBytes(JSON.JsonEncode(htAllSockets)), - SessionFlags.ImportedFromOtherTool | SessionFlags.RequestGeneratedByFiddler | SessionFlags.ResponseGeneratedByFiddler | SessionFlags.ServedFromCache)); + // Don't add a node if there were no secure sockets. + if (htAllSockets.Count > 0) + { + _listSessions.Add(Session.BuildFromData(false, + new HTTPRequestHeaders( + String.Format("/SECURE_SOCKETS"), // TODO: Add Machine name? + new[] { "Host: NETLOG" }), + Utilities.emptyByteArray, + new HTTPResponseHeaders(200, "Analyzed Data", new[] { "Content-Type: application/json; charset=utf-8" }), + Encoding.UTF8.GetBytes(JSON.JsonEncode(htAllSockets)), + SessionFlags.ImportedFromOtherTool | SessionFlags.RequestGeneratedByFiddler | SessionFlags.ResponseGeneratedByFiddler | SessionFlags.ServedFromCache)); + } } catch (Exception e) { FiddlerApplication.Log.LogFormat("GenerateSocketListSession failed: " + DescribeExceptionWithStack(e)); } } diff --git a/FiddlerImportNetlog/Properties/AssemblyInfo.cs b/FiddlerImportNetlog/Properties/AssemblyInfo.cs index ecbc7f9..c8ac932 100644 --- a/FiddlerImportNetlog/Properties/AssemblyInfo.cs +++ b/FiddlerImportNetlog/Properties/AssemblyInfo.cs @@ -12,6 +12,25 @@ // v1.2 // Parse CertificateRequest TLS Handshake message and SSL_HANDSHAKE_MESSAGE_RECEIVED. +// TODO: Surface the CN for each certificate from the server +/* TODO: Parse out messages indicating whether the client sent a cert, and what that cert was. + + t= 7906 [st= 580] SSL_CLIENT_CERT_PROVIDED + --> cert_count = 2 +t= 7906 [st= 580] SSL_HANDSHAKE_MESSAGE_SENT + --> bytes = + 0B 00 0D C0 00 0D BD 00 06 B4 30 82 06 B0 30 82 . .. .. ..0...0. + 04 98 A0 03 02 01 02 02 13 1C 00 4A 4D 7F 50 4B .......... JM.PK + 6F 8E 33 AB 1B 04 00 01 00 4A 4D 7F 30 0D 06 09 o.3... . JM.0... + 2A 86 48 86 F7 0D 01 01 0B 05 00 30 15 31 13 30 *.H....... 0.1.0 + ... + 4D 86 43 E1 23 A0 F9 B7 4F AF 84 AF 48 EC D5 F8 M.C.#...O...H... + DE 4A BD 6B A7 FB 3E 5E 3E E7 8E 11 64 96 2D EB .J.k..>^>...d.-. + 69 0A C8 2C i.., + --> type = 11 + +*/ + // v1.1.2 // Support ZIP compressed JSON logs