The Moose and Squirrel Files

August 26, 2009

Making Checkpoint’s FW Monitor more like Tcpdump

Filed under: checkpoint — Tags: — networknerd @ 10:51 pm

Every checkpoint firewall, regardless of platform, includes the packet capture utility fw monitor. The problem with fw monitor is the cryptic inspect syntax that you need to learn to create a capture filter. Unfortunately, if your looking for support from checkpoint then your stuck with fw monitor. To simplify the process I have created a couple of macros that help bridge the gap between the two syntaxes.

When capturing with tcpdump I generally use the host and port commands to reduce the traffic to a particular set of conversations between hosts. An example expression, in tcp dump syntax, to capture all dns traffic either udp or tcp between 192.168.1.1 and 192.168.1.12 is shown below.

"host 192.168.1.1 and 192.168.1.12 and port 53"

After creating a few simple inspect macros we can do the equivalent  using fw monitor with

accept host(192.168.1.1) and host(192.168.1.12) and port(53);

This is not a bad approximation. The only differences are  brackets needed to pass the parameters to the macro, and a repeat of the host command.

The savings are obvious compared to the complete  inspect script syntax shown below.

accept (
(ip_src=192.168.1.1 or ip_src=192.168.1.12) and \
(ip_dst=192.168.1.1 or ip_dst=192.168.1.12) \
) and \
(
(ip_p=PROTO_tcp and (th_sport=53 or th_dport=53)) or \
(ip_p=PROTO_udp and (uh_sport=53 or uh_dport=53)) \
);

 The macros can be saved in a separate library file and included in a filter file or you can just include all the macros in one large command file with the filter expression as shown below.


#include "tcpip.def"
#define src ip_src
#define dst ip_dst
#define sport th_sport
#define dport th_dport
#define port(portnum) ((ip_p=PROTO_tcp and (sport=portnum or dport=portnum)) or \
(ip_p=PROTO_udp and (uh_sport=portnum or uh_dport=portnum)))
#define srcport(portnum) ((ip_p=PROTO_tcp and sport=portnum) or \
(ip_p=PROTO_udp and uh_sport=portnum))
#define dstport(portnum) ((ip_p=PROTO_tcp and dport=portnum) or \
(ip_p=PROTO_udp and uh_dport=portnum))
#define host(hostip) ((src=hostip) or (dst=hostip))

/* dns traffic between hosts */
accept host(192.168.1.1) and host(192.168.1.12) and port(53);

Once saved to a file, say myfilter.def,  it is a simple matter of running

fw monitor -i -f myfilter.def

and generating, or waiting for the traffic you need to capture.

Advertisements

August 5, 2009

SwitchPort Visualisations

Filed under: audit, Code, Network, visualisation — Tags: , , — networknerd @ 2:58 pm

Richard Bejtlich wrote late last year about an idea for security visualisations which inspired me to look for opportunities to apply visualisations in my work. Well I found that opportunity while performing an audit of switch configurations.

The objectives of the visualisation are to provide at a glance.

  • whether 802.1x is enabled,
  • Vlan/function by color code,
  • trunking mode of the port and
  • the ability to drill down for further information.

I’ve divided the solution into two parts

  1. A script using snmp to query the switch port configuration and save the data in xml format. This can be run as a scheduled task at suitable intervals to ensure that the information remains current. See the listing of spview.wsf below for details.
  2. Converting the saved xml data into a suitable visual representation. For this project an xml stylesheet is used to render the  data as html in a web browser. The drill down component is provided by javascript with a “tooltip text” display when the mouse is moved onto a table cell. See the listing for spview.xsl for more details. Note that the javascript for the ” tooltip text” is courtesy of Nelson and can be found here. The only modifications I made were to the initialisation code so that I could safely move the code from the body of the html to the head section.

Cisco catalyst 3750 48 port switches were used for this project so the snmp OID’s used for checking the configuration are obviously cisco specific.

One thing that really had me stumped was how to include the javascript in the stylesheet without causing errors. I eventually worked out that wrapping everything between, but not including the <script> </script> tags in a <![CDATA[ ….]]> element did the trick.

Switchport Visualisation

Switchport Visualisation

 

 

 

 

 

 

 

spview.xsl

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>

<xsl:variable name="color_legacy" select="'#7bb31a'"/>
<xsl:variable name="color_vc" select="'#ff9d7f'"/>
<xsl:variable name="color_wireless" select="'Red'"/>
<xsl:variable name="color_dot1xauth" select="'#8b88ff'"/>
<xsl:variable name="color_dot1xguest" select="'#8b88ff'"/>
<xsl:variable name="color_printer" select="'lightGrey'"/>
<xsl:variable name="color_reimage" select="'#ff9c00'"/>
<xsl:variable name="color_unknown" select="'#eedb00'"/>
<xsl:variable name="color_nodot1x" select="'#cc3333'"/>
<xsl:variable name="cellheight" select="'35'"/>
<xsl:variable name="cellwidth" select="'35'"/>

<xsl:template match="/">
<html>
<head>
<title><xsl:value-of select="concat('Switch Stack View ',/stack/@hostname)"/></title>
<style type="text/css">
#dhtmltooltip{
position: absolute;
border: 1px solid red;
width: 150px;
padding: 2px;
background-color: lightyellow;
visibility: hidden;
z-index: 100;
filter: progid:DXImageTransform.Microsoft.Shadow(color=gray,direction=115);
}
</style>
<style type="text/css">
table.switch {
table-layout: fixed
}
</style>

<script type="text/javascript">
<![CDATA[
/***********************************************
* Freejavascriptkit.com
* Visit http://www.freejavascriptkit.com for more free Javascripts source code
***********************************************/

var offsetxpoint=-60 //Customize x offset of tooltip
var offsetypoint=20 //Customize y offset of tooltip
var ie=document.all
var ns6=document.getElementById && !document.all
var enabletip=false
var tipobj;

function initTipObj(){
if (ie||ns6)
tipobj=document.all? document.all["dhtmltooltip"] : document.getElementById? document.getElementById("dhtmltooltip") : ""
}
function ietruebody(){
return (document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body
}

function ddrivetip(thetext, thecolor, thewidth){
if (ns6||ie){
if (typeof thewidth!="undefined") tipobj.style.width=thewidth+"px"
if (typeof thecolor!="undefined" && thecolor!="") tipobj.style.backgroundColor=thecolor
tipobj.innerHTML=thetext
enabletip=true
return false
}
}

function positiontip(e){
if (enabletip){
var curX=(ns6)?e.pageX : event.clientX+ietruebody().scrollLeft;
var curY=(ns6)?e.pageY : event.clientY+ietruebody().scrollTop;
//Find out how close the mouse is to the corner of the window
var rightedge=ie&&!window.opera? ietruebody().clientWidth-event.clientX-offsetxpoint : window.innerWidth-e.clientX-offsetxpoint-20
var bottomedge=ie&&!window.opera? ietruebody().clientHeight-event.clientY-offsetypoint : window.innerHeight-e.clientY-offsetypoint-20

var leftedge=(offsetxpoint<0)? offsetxpoint*(-1) : -1000

//if the horizontal distance isn't enough to accomodate the width of the context menu
if (rightedge<tipobj.offsetWidth)
//move the horizontal position of the menu to the left by it's width
tipobj.style.left=ie? ietruebody().scrollLeft+event.clientX-tipobj.offsetWidth+"px" : window.pageXOffset+e.clientX-tipobj.offsetWidth+"px"
else if (curX<leftedge)
tipobj.style.left="5px"
else
//position the horizontal position of the menu where the mouse is positioned
tipobj.style.left=curX+offsetxpoint+"px"

//same concept with the vertical position
if (bottomedge<tipobj.offsetHeight)
tipobj.style.top=ie? ietruebody().scrollTop+event.clientY-tipobj.offsetHeight-offsetypoint+"px" : window.pageYOffset+e.clientY-tipobj.offsetHeight-offsetypoint+"px"
else
tipobj.style.top=curY+offsetypoint+"px"
tipobj.style.visibility="visible"
}
}

function hideddrivetip(){
if (ns6||ie){
enabletip=false
tipobj.style.visibility="hidden"
tipobj.style.left="-1000px"
tipobj.style.backgroundColor=''
tipobj.style.width=''
}
}

document.onmousemove=positiontip
]]>
</script>
</head>
<body onload="initTipObj();">
  <div id="dhtmltooltip"></div>
  <xsl:apply-templates select=".//switch"/>
  <table Border='1' cellspacing='2'>
    <tr>
      <td align='center' bgcolor='{$color_legacy}'></td>
      <td><xsl:text>Legacy Vlan</xsl:text></td>
    </tr>
    <tr>
      <td bgcolor="{$color_dot1xauth}"></td>
      <td><xsl:text>Authenticated Computers Vlan</xsl:text></td>
    </tr>
    <tr>
      <td bgcolor="{$color_dot1xguest}"></td>
      <td>Guest Vlan</td>
    </tr>
    <tr>
      <td bgcolor="{$color_vc}"></td>
      <td><xsl:text>VC Equipment Vlan</xsl:text></td>
    </tr>
    <tr>
      <td bgcolor="{$color_wireless}"></td>
      <td><xsl:text>Wireless or Management Vlan</xsl:text></td>
    </tr>
    <tr>
      <td bgcolor="{$color_printer}"></td>
      <td><xsl:text>Printer Vlan</xsl:text></td>
    </tr>
    <tr>
      <td bgcolor="{$color_reimage}"></td>
      <td><xsl:text>Re-imaging Vlan</xsl:text></td>
    </tr>
    <tr>
      <td bgcolor="{$color_unknown}"></td>
      <td><xsl:text>Unknown Vlan</xsl:text></td>
    </tr>
    <tr>
      <td style="color:{$color_nodot1x}">Text</td>
      <td><xsl:text>Font color indicates access port with no dot1x</xsl:text></td>
    </tr>
  </table>
</body>
</html>
</xsl:template>

<xsl:template match="switch">
  <table class='switch' Border='1' width='100%' cellspacing='2'>
  <tr>
<xsl:comment>Display the odd numbered ports in the top row</xsl:comment>
    <xsl:apply-templates select="port[starts-with(@IfName,'Fa') and substring-after(@IfName,'0/') mod 2 = 1]"/>
  </tr>
  <tr>
<xsl:comment>Display the even numbered ports in the bottom row</xsl:comment>
    <xsl:apply-templates select="port[starts-with(@IfName,'Fa') and substring-after(@IfName,'0/') mod 2 = 0]"/>
  </tr>
  </table>
  <p/><p/>
</xsl:template>

<xsl:template match="port">

  <xsl:variable name="tiptext">
    <xsl:call-template name="tiptext"/>
  </xsl:variable>

  <xsl:variable name="bgcolor">
    <xsl:call-template name="bgcolor"/>
  </xsl:variable>

  <xsl:variable name="cellstyle">
    <xsl:if test="@Dot1x != 2 and @Trunking = 2">
    <xsl:value-of select="concat('color:',$color_nodot1x)"/>
    </xsl:if>
  </xsl:variable>

  <td  align='center' width="{$cellheight}" height="{$cellwidth}" bgcolor="{$bgcolor}" style="{$cellstyle}"
       onMouseover='ddrivetip("{$tiptext}","yellow", 180)'
       onMouseout="hideddrivetip()">
    <xsl:value-of select="substring-after(@IfName,'0/')"/>
    <xsl:if test="@Dot1x = 2">
    <xsl:text>.</xsl:text>
    </xsl:if>
  </td>
</xsl:template>

<xsl:template name="bgcolor">
    <xsl:choose>
      <xsl:when test="@Vlan = 5">
        <xsl:value-of select="$color_legacy"/>
      </xsl:when>
      <xsl:when test="@Vlan = 910">
        <xsl:value-of select="$color_vc"/>
      </xsl:when>
      <xsl:when test="(@Vlan &gt;= 100) and (@Vlan &lt;= 199)and ((@Vlan mod 4) = 0)">
        <xsl:value-of select="$color_wireless"/>
      </xsl:when>
      <xsl:when test="(@Vlan &gt;= 200) and (@Vlan &lt;= 387) and ((@Vlan mod 20) = 0)">
        <xsl:value-of select="$color_dot1xauth"/>
      </xsl:when>
      <xsl:when test="(@Vlan &gt;= 200) and (@Vlan &lt;= 387) and ((@Vlan mod 20) = 5)">
        <xsl:value-of select="$color_dot1xguest"/>
      </xsl:when>
      <xsl:when test="(@Vlan &gt;= 200) and (@Vlan &lt;= 387) and ((@Vlan mod 20) = 4)">
        <xsl:value-of select="$color_printer"/>
      </xsl:when>
      <xsl:when test="(@Vlan &gt;= 200) and (@Vlan &lt;= 387) and ((@Vlan mod 20) = 7)">
        <xsl:value-of select="$color_reimage"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$color_unknown"/>
      </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template name="tiptext">
    <xsl:value-of select="concat('Port: ',@IfName)"/>
    <xsl:text>&lt;BR/&gt;</xsl:text>
    <xsl:choose>
      <xsl:when test="@Dot1x = 1">
        <xsl:value-of select="'Dot1x: Force-Unauthorised'"/>
      </xsl:when>
      <xsl:when test="@Dot1x = 2">
        <xsl:value-of select="'Dot1x: Auto'"/>
      </xsl:when>
      <xsl:when test="@Dot1x = 3">
        <xsl:value-of select="'Dot1x: Force-Authorised'"/>
      </xsl:when>
      <xsl:when test="@Dot1x = ''">
        <xsl:value-of select="'Dot1x: None'"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="'Dot1x: Unknown'"/>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:text>&lt;BR/&gt;</xsl:text>
    <xsl:choose>
      <xsl:when test="@Trunking = 1">
        <xsl:value-of select="'Trunking: On'"/>
      </xsl:when>
      <xsl:when test="@Trunking = 2">
        <xsl:value-of select="'Trunking: Off'"/>
      </xsl:when>
      <xsl:when test="@Trunking = 3">
        <xsl:value-of select="'Trunking: Desirable'"/>
      </xsl:when>
      <xsl:when test="@Trunking = 4">
        <xsl:value-of select="'Trunking: Auto'"/>
      </xsl:when>
      <xsl:when test="@Trunking = 5">
        <xsl:value-of select="'Trunking: OnNoNegotiate'"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="'Trunking: Unknown'"/>
      </xsl:otherwise>
    </xsl:choose>
    <xsl:text>&lt;BR/&gt;</xsl:text>
    <xsl:value-of select="concat('Vlan: ',@Vlan)"/>
    <xsl:text>&lt;BR/&gt;</xsl:text>
    <xsl:value-of select="concat('Desc: ',@Description)"/>
    <xsl:text>&lt;BR/&gt;</xsl:text>
</xsl:template>
</xsl:stylesheet>

spview.wsf

<package>
<job id="spview">
<runtime>
<named
  name="stylesheet"
  helpstring="File path of the xml stylesheet to be referenced in the xml file."
  many="false"
  required="True"
  type=string
/>
<named
  name="agent"
  helpstring="Host name or ip address of the switch to query"
  many="false"
  required="True"
  type=string
/>
<named
  name="outfile"
  helpstring="Path to the file where the configuration data will be output"
  many="false"
  required="True"
  type=string
/>
</runtime>

<script language=vbscript>
option explicit

dim counter
dim REQ_ARGNAMES

'Constants to validate our Arguments against expectations
Const REQ_ARGCOUNT=3
Const cSSARG="stylesheet"
Const cAGENT="agent"
Const cOFILE="outfile"

'*****************************************************************************
'Argument Validation  Code - "Time spent on reconaissance is seldom wasted!" *
'*****************************************************************************
'Validate all our arguments before proceeding - add more validation code as required
'Initialise the array of Argument names for the named arguments
REQ_ARGNAMES=array(cSSARG,cAGENT)

'Do we have the correct number of named arguments
If wscript.Arguments.named.count < REQ_ARGCOUNT Then
  wscript.echo "Incorrect number of named arguments were specified!"
  wscript.Arguments.ShowUsage
  wscript.sleep 1000
  wscript.Quit
End If

'Was the script passed a named argument value for all arguments we expected
for counter = lbound(REQ_ARGNAMES) to ubound(REQ_ARGNAMES)
  If wscript.arguments.named(REQ_ARGNAMES(counter)) = "" then
     wscript.echo "Expected a named argument for " & REQ_ARGNAMES(counter)
     wscript.Arguments.ShowUsage
     wscript.sleep 1000
     wscript.Quit
  End If
next ' counter

'Validation to do list
'The existence of the stylesheet is not validated
'The ability to create the output file is not checked.
'Return codes from snmp query to switch are not checked
'*****************************************************************************
'End Argument Validation - insert more validation tests above this line.     *
'*****************************************************************************

const PORTIFINDEX = " .1.3.6.1.4.1.9.5.1.4.1.1.11 "
const IFNAME = " .1.3.6.1.2.1.31.1.1.1.1 "
const VMVLAN = " .1.3.6.1.4.1.9.9.68.1.2.2.1.2. "
const IFALIAS = " .1.3.6.1.2.1.31.1.1.1.18 "
const VLANPORTVLAN = " .1.3.6.1.4.1.9.5.1.9.3.1.3 "
const VLANPORTISLADMINSTATUS = " .1.3.6.1.4.1.9.5.1.9.3.1.7 "
const SYSNAME = " .1.3.6.1.2.1.1.5.0 "
const dot1xAuthAuthControlledPortControl = " .1.0.8802.1.1.1.1.2.1.1.6 "
const SNMPWALKCMD = "f:\usr\bin\snmpwalk.exe -OnqUe -v 2c -c "
const SNMPREAD = " public "

dim strRetcode, key, value, strHostName
dim intCurrentSwitch, intSwitch

dim objIfindexName ' holds a dictionary filled by the getIfName function
dim objPIfindex ' holds a dictionary filled by the getPortIfIndex function
dim objIfindexAlias ' holds a dictionary filled by the getIfAlias function
dim objIfindexDot1x ' holds a dictionary filled by the getDot1x function
dim objPIfindexTrunk ' holds a dictionary filled by the getTrunkStatus function
dim objPIfindexVlan ' holds a dictionary filled by the getVlan function
dim intSwitchCount ' number of switches in the stack
dim strAttrIfName, strAttrDot1x, strAttrVlan
dim strAttrTrunk, strAttrDesc, strtemp
dim objDom 'As DOMDocument
dim objStackElement 'As IXMLDOMElement
dim objSwitch 'As IXMLDOMElement
dim objSwitchCount 'As IXMLDOMAttribute
dim objStackName 'As IXMLDOMAttribute
dim objSwitchNum 'As IXMLDOMAttribute
dim objText 'As IXMLDOMText
dim objPort 'As IXMLDOMElement
dim objPortAttrib 'As IXMLDOMAttribute
dim objPI  'As IXMLDOMProcessingInstruction

'****************************************************************************
'* Retrieve the switch port configuration data                              *
'****************************************************************************
strHostName = ""
strRetcode =  getHostName(wscript.arguments.named(cAGENT),strHostName)

strRetcode =  getPortIfIndex(wscript.arguments.named(cAGENT),objPIfindex)
' Get the number of switches in the stack.
intSwitchCount = 0
for each key in objPIfindex.keys
  if (cint(left(key,instr(key,".")-1)) > intSwitchCount) then
    intSwitchCount = cint(left(key,instr(key,".")-1))
  end if
next

strRetcode =  getIfName(wscript.arguments.named(cAGENT),objIfindexName)

strRetcode =  getIfAlias(wscript.arguments.named(cAGENT),objIfindexAlias)

strRetcode =  getDot1x(wscript.arguments.named(cAGENT),objIfindexDot1x)

strRetcode =  getTrunkStatus(wscript.arguments.named(cAGENT),objPIfindexTrunk)

strRetcode =  getVlan(wscript.arguments.named(cAGENT),objPIfindexVlan)

'****************************************************************************
'* Write the data to xml nodes and save to file                             *
'****************************************************************************
'Create the DOM document and processing instructions for version & stylesheet
Set objDom = CreateObject("Msxml2.DomDocument.4.0")
objDom.preserveWhiteSpace = 1
Set objPI = objDom.createProcessingInstruction("xml-stylesheet", "type='text/xsl' href='" & wscript.arguments.named(cSSARG) &"'")
objDom.insertBefore objPI, objDom.childNodes.Item(0)
Set objPI = objDom.createProcessingInstruction("xml", "version='1.0'")
objDom.insertBefore objPI, objDom.childNodes.Item(0)

'Creates root element, stack to represent a switch stack
Set objStackElement = objDom.createElement("stack")
objDom.appendChild objStackElement
objStackElement.Text = vbcrlf

'Creates Attribute to the stack Element = hostname of stack
Set objStackName = objDom.createAttribute("hostname")
objStackName.nodeValue = strHostName
objStackElement.setAttributeNode objStackName

'Creates Attribute to the stack Element = number of switches in stack
Set objSwitchCount = objDom.createAttribute("SwitchCount")
objSwitchCount.nodeValue = intSwitchCount
objStackElement.setAttributeNode objSwitchCount

'Loop through all the ports in the switch stack and save their config
intCurrentSwitch = 0
for each key in objPIfindex.keys()
  intSwitch = cint(left(key,instr(key,".")-1))
  if (intSwitch <> intCurrentSwitch) then 'next switch in the stack
     intCurrentSwitch = intSwitch
     ' Creates Switch element as a child of stack
     Set objSwitch = objDom.createElement("switch")
     objStackElement.appendChild objSwitch
     objSwitch.Text = vbcrlf
     ' Creates Attribute to the switch Element
     Set objSwitchNum = objDom.createAttribute("Number")
     objSwitchNum.nodeValue = intSwitch
     objSwitch.setAttributeNode objSwitchNum
     Set objSwitchNum = Nothing
     'Make the xml prettier else it is saved on a single line
     set objText = objDom.CreateTextNode(vbcrlf)
     objStackElement.appendChild objText
     set objText = Nothing
  end if

  'Create a port element and set the attributes
  Set objPort = objDom.createElement("port")
  objSwitch.appendChild objPort
  ' Creates PortIfIndex Attribute to the port Element
  Set objPortAttrib = objDom.createAttribute("PortIfIndex")
  objPortAttrib.nodeValue = key
  objPort.setAttributeNode objPortAttrib

  if objIfindexName.exists(objPIfindex.item(key)) then
    strAttrIfName = objIfindexName.item(objPIfindex.item(key))
  else
    strAttrIfName = ""
  end if
  ' Creates IfName Attribute to the port Element
  Set objPortAttrib = objDom.createAttribute("IfName")
  objPortAttrib.nodeValue = strAttrIfName
  objPort.setAttributeNode objPortAttrib

  if objIfindexDot1x.exists(objPIfindex.item(key)) then
    strAttrDot1x = objIfindexDot1x.item(objPIfindex.item(key))
  else
    strAttrDot1x = ""
  end if
  ' Creates Dot1x Attribute to the port Element
  Set objPortAttrib = objDom.createAttribute("Dot1x")
  objPortAttrib.nodeValue = strAttrDot1x
  objPort.setAttributeNode objPortAttrib

  if objPIfindexVlan.exists(key) then
    strAttrVlan = objPIfindexVlan.item(key)
  else
    strAttrVlan = ""
  end if
  ' Creates Vlan Attribute to the port Element
  Set objPortAttrib = objDom.createAttribute("Vlan")
  objPortAttrib.nodeValue = strAttrVlan
  objPort.setAttributeNode objPortAttrib

  if objPIfindexTrunk.exists(key) then
    strAttrTrunk = objPIfindexTrunk.item(key)
  else
    strAttrTrunk = ""
  end if
  ' Creates Trunking Attribute to the port Element
  Set objPortAttrib = objDom.createAttribute("Trunking")
  objPortAttrib.nodeValue = strAttrTrunk
  objPort.setAttributeNode objPortAttrib

  if objIfindexAlias.exists(objPIfindex.item(key)) then
    strAttrDesc = objIfindexAlias.item(objPIfindex.item(key))
  else
    strAttrDesc = ""
  end if
  ' Creates Description Attribute to the port Element
  Set objPortAttrib = objDom.createAttribute("Description")
  objPortAttrib.nodeValue = strAttrDesc
  objPort.setAttributeNode objPortAttrib
  'Make the xml prettier else it is saved on a single line
  set objText = objDom.CreateTextNode(vbcrlf)
  objSwitch.appendChild objText
  set objText = Nothing
  ' Saves XML data to disk.
  objDom.save (wscript.arguments.named(cOFILE))
next

wscript.quit

'************************************************************************
'FUNCTION:                                                              *
'       getPortIfIndex(strAgent,objPortIfIndex)                         *
'                                                                       *
'Purpose:                                                               *
'       walk the CISCO-STACK-MIB::portIfIndex OID and populate the      *
'       dictionary object passed                                        *
'                                                                       *
'Inputs:                                                                *
'       strAgent: management IP address of the switch                   *
'       objPortIfIndex: dictionary to hold the port interface indices   *
'                                                                       *
'Returns:                                                               *
'       Integer, 0 if successful or a positive value on failure.        *
'                                                                       *
'Calls:                                                                 *
'       SNMPWALKCMD - constant defining the path to an external         *
'       program and options used to perform an snmp set                 *
'                                                                       *
'Comments:                                                              *
'       CISCO-STACK-MIB is cisco specific.                              *
'************************************************************************
function  getPortIfIndex(strAgent,objPortIfIndex)
dim WshShell, oExec
dim re 'as regexp
dim matches
dim match
dim tempstr, stroutput, strErr

  set objPortIfIndex = CreateObject("Scripting.Dictionary")
  Set WshShell = CreateObject("wscript.Shell")
  Set oExec = WshShell.Exec(SNMPWALKCMD & SNMPREAD & strAgent & " " & _
				PORTIFINDEX)
  Do while Not oExec.StdOut.AtEndOfStream
    stroutput = oExec.StdOut.readall
  Loop
  Do while Not oExec.StdErr.AtEndOfStream
    strErr = oExec.StdErr.readall
  Loop
  Do While oExec.Status <> 1
    wscript.Sleep 100
  Loop
  if (len(strErr) = 0) then
    set re = new regexp
    re.global = True
    re.multiline = True
'Pattern to capture the last digits of the snmp output
'output lines from SNMPCMD should look like
'                ".1.3.6.1.4.1.9.5.1.4.1.1.11.4.49 11545"
    re.pattern = "^" & replace(trim(PORTIFINDEX),".","\.") & _
			"\.(\d+\.\d+)\s+(\d+)$"

    set matches = re.execute(stroutput)
    for each match in matches
      objPortIfIndex.add match.submatches(0), match.submatches(1)
    next
  end if
  getPortIfIndex = len(strErr)
end function

'************************************************************************
'FUNCTION:                                                              *
'       getIfName(strAgent,objIfIndexName)                              *
'                                                                       *
'Purpose:                                                               *
'       walk the IF-MIB::ifName OID and populate the dictionary object  *
'        passed                                                         *
'                                                                       *
'Inputs:                                                                *
'       strAgent: management IP address of the switch                   *
'       objIfIndexName: dictionary to hold the port interface index to  *
'        name mappings                                                  *
'                                                                       *
'Returns:                                                               *
'       Integer, 0 if successful or a positive value on failure.        *
'                                                                       *
'Calls:                                                                 *
'       SNMPWALKCMD - constant defining the path to an external         *
'       program and options used to perform an snmp set                 *
'                                                                       *
'Comments:                                                              *
'       CISCO-STACK-MIB is cisco specific.                              *
'************************************************************************
function  getIfName(strAgent,objIfIndexName)
dim WshShell, oExec
dim re 'as regexp
dim matches
dim match
dim tempstr, stroutput, strErr

  set objIfIndexName = CreateObject("Scripting.Dictionary")
  Set WshShell = CreateObject("wscript.Shell")
  Set oExec = WshShell.Exec(SNMPWALKCMD & SNMPREAD & strAgent & " " & _
				IFNAME)
  Do while Not oExec.StdOut.AtEndOfStream
    stroutput = oExec.StdOut.readall
  Loop
  Do while Not oExec.StdErr.AtEndOfStream
    strErr = oExec.StdErr.readall
  Loop
  Do While oExec.Status <> 1
    wscript.Sleep 100
  Loop
  if (len(strErr) = 0) then
    set re = new regexp
    re.global = True
    re.multiline = True
'Pattern to capture the last digits of the snmp output
'output lines from SNMPCMD should look like
'                ".1.3.6.1.2.1.31.1.1.1.1.10001 Fa1/0/1"
    re.pattern = "^" & replace(trim(IFNAME),".","\.") & _
			"\.(\d+)\s+([^\r\n]+)$"

    set matches = re.execute(stroutput)
    for each match in matches
      objIfIndexName.add match.submatches(0), match.submatches(1)
    next
  end if
  getIfName = len(strErr)
end function

'************************************************************************
'FUNCTION:                                                              *
'       getIfAlias(strAgent,objIfIndexDesc)                              *
'                                                                       *
'Purpose:                                                               *
'       walk the IF-MIB::ifAlias OID and populate the dictionary object *
'        passed                                                         *
'                                                                       *
'Inputs:                                                                *
'       strAgent: management IP address of the switch                   *
'       objIfIndexDesc: dictionary to hold the port interface index to  *
'        description mappings                                           *
'                                                                       *
'Returns:                                                               *
'       Integer, 0 if successful or a positive value on failure.        *
'                                                                       *
'Calls:                                                                 *
'       SNMPWALKCMD - constant defining the path to an external         *
'       program and options used to perform an snmp set                 *
'                                                                       *
'Comments:                                                              *
'       CISCO-STACK-MIB is cisco specific.                              *
'************************************************************************
function  getIfAlias(strAgent,objIfIndexDesc)
dim WshShell, oExec
dim re 'as regexp
dim matches
dim match
dim tempstr, stroutput, strErr

  set objIfIndexDesc = CreateObject("Scripting.Dictionary")
  Set WshShell = CreateObject("wscript.Shell")
  Set oExec = WshShell.Exec(SNMPWALKCMD & SNMPREAD & strAgent & " " & _
				IFALIAS)
  Do while Not oExec.StdOut.AtEndOfStream
    stroutput = oExec.StdOut.readall
  Loop
  Do while Not oExec.StdErr.AtEndOfStream
    strErr = oExec.StdErr.readall
  Loop
  Do While oExec.Status <> 1
    wscript.Sleep 100
  Loop
  if (len(strErr) = 0) then
    set re = new regexp
    re.global = True
    re.multiline = True
'Pattern to capture the snmp output
'output lines from SNMPCMD should look like
'                ".1.3.6.1.2.1.31.1.1.1.18.11543 Printer port"
    re.pattern = "^" & replace(trim(IFALIAS),".","\.") & _
			"\.(\d+)\s{1}([^\r\n]*)$"

    set matches = re.execute(stroutput)
    for each match in matches
      objIfIndexDesc.add match.submatches(0), match.submatches(1)
    next
  end if
  getIfAlias = len(strErr)
end function

'************************************************************************
'FUNCTION:                                                              *
'       getDot1x(strAgent,objIfIndexDot1x)                              *
'                                                                       *
'Purpose:                                                               *
'       walk the IEEE8021-PAE-MIB::dot1xAuthAuthControlledPortControl   *
'        OID and populate the dictionary object passed                  *
'                                                                       *
'Inputs:                                                                *
'       strAgent: management IP address of the switch                   *
'       objIfIndexDot1x: dictionary to hold the port interface index to *
'        802.1x mappings                                                *
'                                                                       *
'Returns:                                                               *
'       Integer, 0 if successful or a positive value on failure.        *
'                                                                       *
'Calls:                                                                 *
'       SNMPWALKCMD - constant defining the path to an external         *
'       program and options used to perform an snmp set                 *
'                                                                       *
'Comments:                                                              *
'       None.                                                           *
'************************************************************************
function  getDot1x(strAgent,objIfIndexDot1x)
dim WshShell, oExec
dim re 'as regexp
dim matches
dim match
dim tempstr, stroutput, strErr

  set objIfIndexDot1x = CreateObject("Scripting.Dictionary")
  Set WshShell = CreateObject("wscript.Shell")
  Set oExec = WshShell.Exec(SNMPWALKCMD & SNMPREAD & strAgent & " " & _
				dot1xAuthAuthControlledPortControl)
  Do while Not oExec.StdOut.AtEndOfStream
    stroutput = oExec.StdOut.readall
  Loop
  Do while Not oExec.StdErr.AtEndOfStream
    strErr = oExec.StdErr.readall
  Loop
  Do While oExec.Status <> 1
    wscript.Sleep 100
  Loop

  if (len(strErr) = 0) then
    set re = new regexp
    re.global = True
    re.multiline = True
'Pattern to capture the last digits of the snmp output
'output lines from SNMPCMD should look like
'                ".1.0.8802.1.1.1.1.2.1.1.6.11515 2"
    re.pattern = "^" & replace(trim(dot1xAuthAuthControlledPortControl),".","\.") & _
			"\.(\d+)\s+(\d)$"

    set matches = re.execute(stroutput)
    for each match in matches
      objIfIndexDot1x.add match.submatches(0), match.submatches(1)
    next
  end if
  getDot1x = len(strErr)
end function

'************************************************************************
'FUNCTION:                                                              *
'       getTrunkStatus(strAgent,objPortIfIndexTrunk)                    *
'                                                                       *
'Purpose:                                                               *
'       walk the CISCO-STACK-MIB::vlanPortIslAdminStatus OID and        *
'       populate the dictionary object passed                           *
'                                                                       *
'Inputs:                                                                *
'       strAgent: management IP address of the switch                   *
'       objPortIfIndexTrunk: dictionary to hold the port interface index*
'         to trunk status                                               *
'                                                                       *
'Returns:                                                               *
'       Integer, 0 if successful or a positive value on failure.        *
'                                                                       *
'Calls:                                                                 *
'       SNMPWALKCMD - constant defining the path to an external         *
'       program and options used to perform an snmp set                 *
'                                                                       *
'Comments:                                                              *
'       CISCO-STACK-MIB is cisco specific.                              *
'************************************************************************
function  getTrunkStatus(strAgent,objPortIfIndexTrunk)
dim WshShell, oExec
dim re 'as regexp
dim matches
dim match
dim tempstr, stroutput, strErr

  set objPortIfIndexTrunk = CreateObject("Scripting.Dictionary")
  Set WshShell = CreateObject("wscript.Shell")
  Set oExec = WshShell.Exec(SNMPWALKCMD & SNMPREAD & strAgent & " " & _
				VLANPORTISLADMINSTATUS)
  Do while Not oExec.StdOut.AtEndOfStream
    stroutput = oExec.StdOut.readall
  Loop
  Do while Not oExec.StdErr.AtEndOfStream
    strErr = oExec.StdErr.readall
  Loop
  Do While oExec.Status <> 1
    wscript.Sleep 100
  Loop
  if (len(strErr) = 0) then
    set re = new regexp
    re.global = True
    re.multiline = True
'Pattern to capture the last digits of the snmp output
'output lines from SNMPCMD should look like
'                ".1.3.6.1.4.1.9.5.1.9.3.1.7.4.44 2"
    re.pattern = "^" & replace(trim(VLANPORTISLADMINSTATUS),".","\.") & _
			"\.(\d+\.\d+)\s+(\d+)$"

    set matches = re.execute(stroutput)
    for each match in matches
      objPortIfIndexTrunk.add match.submatches(0), match.submatches(1)
    next
  end if
  getTrunkStatus = len(strErr)
end function

'************************************************************************
'FUNCTION:                                                              *
'       getVlan(strAgent,objPortIfIndexVlan)                         *
'                                                                       *
'Purpose:                                                               *
'       walk the CISCO-STACK-MIB::vlanPortIslAdminStatus OID and        *
'       populate the dictionary object passed                           *
'                                                                       *
'Inputs:                                                                *
'       strAgent: management IP address of the switch                   *
'       objPortIfIndexVlan: dictionary to hold the port interface index *
'         to vlan mapping                                               *
'                                                                       *
'Returns:                                                               *
'       Integer, 0 if successful or a positive value on failure.        *
'                                                                       *
'Calls:                                                                 *
'       SNMPWALKCMD - constant defining the path to an external         *
'       program and options used to perform an snmp set                 *
'                                                                       *
'Comments:                                                              *
'       CISCO-STACK-MIB is cisco specific.                              *
'************************************************************************
function  getVlan(strAgent,objPortIfIndexVlan)
dim WshShell, oExec
dim re 'as regexp
dim matches
dim match
dim tempstr, stroutput, strErr

  set objPortIfIndexVlan = CreateObject("Scripting.Dictionary")
  Set WshShell = CreateObject("wscript.Shell")
  Set oExec = WshShell.Exec(SNMPWALKCMD & SNMPREAD & strAgent & " " & _
				VLANPORTVLAN)
  Do while Not oExec.StdOut.AtEndOfStream
    stroutput = oExec.StdOut.readall
  Loop
  Do while Not oExec.StdErr.AtEndOfStream
    strErr = oExec.StdErr.readall
  Loop
  Do While oExec.Status <> 1
    wscript.Sleep 100
  Loop
  if (len(strErr) = 0) then
    set re = new regexp
    re.global = True
    re.multiline = True
'Pattern to capture the last digits of the snmp output
'output lines from SNMPCMD should look like
'                ".1.3.6.1.4.1.9.5.1.9.3.1.3.4.46 810"
    re.pattern = "^" & replace(trim(VLANPORTVLAN),".","\.") & _
			"\.(\d+\.\d+)\s+(\d+)$"

    set matches = re.execute(stroutput)
    for each match in matches
      objPortIfIndexVlan.add match.submatches(0), match.submatches(1)
    next
  end if
  getVlan = len(strErr)
end function

'************************************************************************
'FUNCTION:                                                              *
'       getHostName(strAgent,strHostName)                               *
'                                                                       *
'Purpose:                                                               *
'       walk the SNMPv2-MIB::sysName.0 OID and                          *
'       copy the hostname into strHostName                              *
'                                                                       *
'Inputs:                                                                *
'       strAgent: management IP address of the switch                   *
'       strHostName:  string variable reference to hold the hostname    *
'                                                                       *
'Returns:                                                               *
'       Integer, 0 if successful or a positive value on failure.        *
'                                                                       *
'Calls:                                                                 *
'       SNMPWALKCMD - constant defining the path to an external         *
'       program and options used to perform an snmp set                 *
'                                                                       *
'Comments:                                                              *
'       None.                                                           *
'************************************************************************
function  getHostName(strAgent,strHostName)
dim WshShell, oExec
dim re 'as regexp
dim matches
dim match
dim tempstr, stroutput, strErr

  Set WshShell = CreateObject("wscript.Shell")
  Set oExec = WshShell.Exec(SNMPWALKCMD & SNMPREAD & strAgent & " " & _
				SYSNAME)
  Do while Not oExec.StdOut.AtEndOfStream
    stroutput = oExec.StdOut.readall
  Loop
  Do while Not oExec.StdErr.AtEndOfStream
    strErr = oExec.StdErr.readall
  Loop
  Do While oExec.Status <> 1
    wscript.Sleep 100
  Loop
  if (len(strErr) = 0) then
    set re = new regexp
    re.global = True
    re.multiline = True
'Pattern to capture the snmp output
'output lines from SNMPCMD should look like
'                ".1.3.6.1.2.1.1.5.0 Sydney-Switch"
    re.pattern = "^" & replace(trim(SYSNAME),".","\.") & _
			"\s{1}([^\r\n]*)$"

    set matches = re.execute(stroutput)
    for each match in matches
      strHostname = match.submatches(0)
    next
  end if
  getHostName = len(strErr)
end function

</script>
</job>
</package>

February 28, 2009

Combine Wireshark Summary and Detail Information with XML Joins

Filed under: Code, Network — Tags: , , , , — networknerd @ 8:45 am

Wireshark users may occasionally find themselves wishing for the ability the add some packet detail to the summary information. In the previous post I was looking at DSCP  and TOS information and wanted to add that to the summary rather than drilling down into every packet.  The first solution is to use Tshark and a lua script as I did in the previous post.  The second solution is to export the capture file in both PSML and PDML format packet detail and render them in a web browser.

PSML and PDML are both XML files, so they can be rendered using an XML stylesheet and displayed in a web browser. Sensibly parsing the output of two different XML files can be a bit tricky. Fortunately there is a common field in each file, the packet number, which can be used to perform the equivalent of an SQL join on the two files.

First I captured the request and response of two single pings, one with and one without the ToS byte set.  Then I exported the files in PDML and PSML formats as shown below.  Note the reference in line 2 of packetsumm2.xml to the stylesheet table7.xsl.  When using a browser to transform the xml we have to modify it manually to include the reference rather than pass it as a command line parameter like we would with saxon or xalan.

The important parts of the stylesheet are highlighted in red.  The first of the highlighted lines creates a reference to the document element of the packet details file. The template below does all the hard work of performing the join.

<xsl:template match="/psml/packet">
      <tr>
  <xsl:variable name="packetnum" select="section[1]"/>
  <xsl:for-each select="section">
    <xsl:if test="position()=last()">
        <td><xsl:value-of select= "$packetdetail/pdml/packet/proto[@name = 'geninfo']/field[@name = 'num' and @show = $packetnum]/../../proto[@name = 'ip']/field[@name='ip.dsfield']/@showname"/></td>
    </xsl:if>
    <td><xsl:value-of select="."/></td>
  </xsl:for-each>
      </tr>
</xsl:template>

The packet number is in the first element and is saved in the variable packetnum.  A for-each  loop is created to output all the section elements of the packet summary.  In this case they are “No.”,  “Time”,  ” Source”,  ” Destination”,  ” Protocol” and  “Info”. As the loop progresses we test to see if we are at the last “section” element, and if we are it inserts the DS field information from the packet detail file. Now this is where the going gets heavy. We insert the DS field information using a <xsl:value-of> tag,  which contains a select attribute with an xpath expression to that information.

There are two main parts to this xpath expression

  1. $packetdetail/pdml/packet/proto[@name = 'geninfo']/field[@name = 'num' and @show = $packetnum]/
  2. ../../proto[@name = 'ip']/field[@name='ip.dsfield']/@showname

Part 1 drills down to the proto element of the packet that has  a field element with a name attribute equal to num and a show attribute equal to the packetnum variable.  This is the common part where we perform the join on the two files.

Part 2 solves the problem of accessing the DS field information.  This is a problem because our xpath expression has already taken us down one proto element and we need to be in another proto element at the same level. To get there we need to go back to the common ancestor of the two proto elements, using the ../.. expression and then match the proto element with a name attribute of ip and field element with a name attribute of ip.dsfield and finally selecting the showname attribute.

Conclusion

I admit the example using wireshark is a little contrived.  However, the ability to join xml files on a common field is a powerful technique worth keeping in the toolkit.  Who knows somebody may actually wish to display packet capture information in a web browser.

Table7.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:variable name="packetdetail" select="document('packets2.xml')"/>

<xsl:template match="/psml">
  <html>
  <body>
    <table border="2" bgcolor="lightgrey">
      <xsl:apply-templates/>
    </table>
  </body>
  </html>
</xsl:template>

<xsl:template match="/psml/structure">
      <tr>
  <xsl:for-each select="section">
  <xsl:if test="position() = last()">
        <th>DS Field</th>
  </xsl:if>
        <th><xsl:value-of select="."/></th>
  </xsl:for-each>
      </tr>
</xsl:template>
<xsl:template match="/psml/packet">
      <tr>
  <xsl:variable name="packetnum" select="section[1]"/>
  <xsl:for-each select="section">
    <xsl:if test="position()=last()">
        <td><xsl:value-of select= "$packetdetail/pdml/packet/proto[@name = 'geninfo']/field[@name = 'num' and @show = $packetnum]/../../proto[@name = 'ip']/field[@name='ip.dsfield']/@showname"/></td>
    </xsl:if>
    <td><xsl:value-of select="."/></td>
  </xsl:for-each>
      </tr>
</xsl:template>
</xsl:stylesheet>

Packetsumm2.xml

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="table7.xsl"?>
<psml version="0" creator="wireshark/1.0.2">
<structure>
<section>No.</section>
<section>Time</section>
<section>Source</section>
<section>Destination</section>
<section>Protocol</section>
<section>Info</section>
</structure>

<packet>
<section>1</section>
<section>0.000000</section>
<section>192.168.0.7</section>
<section>74.125.19.147</section>
<section>ICMP</section>
<section>Echo (ping) request</section>
</packet>

<packet>
<section>2</section>
<section>0.181465</section>
<section>74.125.19.147</section>
<section>192.168.0.7</section>
<section>ICMP</section>
<section>Echo (ping) reply</section>
</packet>

<packet>
<section>3</section>
<section>9.897599</section>
<section>192.168.0.7</section>
<section>74.125.19.147</section>
<section>ICMP</section>
<section>Echo (ping) request</section>
</packet>

<packet>
<section>4</section>
<section>10.079768</section>
<section>74.125.19.147</section>
<section>192.168.0.7</section>
<section>ICMP</section>
<section>Echo (ping) reply</section>
</packet>

</psml>

Packets2.xml

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="packets.xsl"?>
<pdml version="0" creator="wireshark/1.0.2">
<packet>
  <proto name="geninfo" pos="0" showname="General information" size="74">
    <field name="num" pos="0" show="1" showname="Number" value="1" size="74"/>
    <field name="len" pos="0" show="74" showname="Packet Length" value="4a" size="74"/>
    <field name="caplen" pos="0" show="74" showname="Captured Length" value="4a" size="74"/>
    <field name="timestamp" pos="0" show="Jan  8, 2009 10:14:57.971166000" showname="Captured Time" value="1231373697.971166000" size="74"/>
  </proto>
  <proto name="frame" showname="Frame 1 (74 bytes on wire, 74 bytes captured)" size="74" pos="0">
    <field name="frame.time" showname="Arrival Time: Jan  8, 2009 10:14:57.971166000" size="0" pos="0" show="Jan  8, 2009 10:14:57.971166000"/>
    <field name="frame.time_delta" showname="Time delta from previous captured frame: 0.000000000 seconds" size="0" pos="0" show="0.000000000"/>
    <field name="frame.time_delta_displayed" showname="Time delta from previous displayed frame: 0.000000000 seconds" size="0" pos="0" show="0.000000000"/>
    <field name="frame.time_relative" showname="Time since reference or first frame: 0.000000000 seconds" size="0" pos="0" show="0.000000000"/>
    <field name="frame.number" showname="Frame Number: 1" size="0" pos="0" show="1"/>
    <field name="frame.pkt_len" showname="Packet Length: 74 bytes" hide="yes" size="0" pos="0" show="74"/>
    <field name="frame.len" showname="Frame Length: 74 bytes" size="0" pos="0" show="74"/>
    <field name="frame.cap_len" showname="Capture Length: 74 bytes" size="0" pos="0" show="74"/>
    <field name="frame.marked" showname="Frame is marked: False" size="0" pos="0" show="0"/>
    <field name="frame.protocols" showname="Protocols in frame: eth:ip:icmp:data" size="0" pos="0" show="eth:ip:icmp:data"/>
  </proto>
  <proto name="eth" showname="Ethernet II, Src: Intel_28:c7:f7 (00:18:de:28:c7:f7), Dst: Netgear_ea:06:78 (00:09:5b:ea:06:78)" size="14" pos="0">
    <field name="eth.dst" showname="Destination: Netgear_ea:06:78 (00:09:5b:ea:06:78)" size="6" pos="0" show="00:09:5b:ea:06:78" value="00095bea0678">
      <field name="eth.addr" showname="Address: Netgear_ea:06:78 (00:09:5b:ea:06:78)" size="6" pos="0" show="00:09:5b:ea:06:78" value="00095bea0678"/>
      <field name="eth.ig" showname=".... ...0 .... .... .... .... = IG bit: Individual address (unicast)" size="3" pos="0" show="0" value="0" unmaskedvalue="00095b"/>
      <field name="eth.lg" showname=".... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)" size="3" pos="0" show="0" value="0" unmaskedvalue="00095b"/>
    </field>
    <field name="eth.src" showname="Source: Intel_28:c7:f7 (00:18:de:28:c7:f7)" size="6" pos="6" show="00:18:de:28:c7:f7" value="0018de28c7f7">
      <field name="eth.addr" showname="Address: Intel_28:c7:f7 (00:18:de:28:c7:f7)" size="6" pos="6" show="00:18:de:28:c7:f7" value="0018de28c7f7"/>
      <field name="eth.ig" showname=".... ...0 .... .... .... .... = IG bit: Individual address (unicast)" size="3" pos="6" show="0" value="0" unmaskedvalue="0018de"/>
      <field name="eth.lg" showname=".... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)" size="3" pos="6" show="0" value="0" unmaskedvalue="0018de"/>
    </field>
    <field name="eth.type" showname="Type: IP (0x0800)" size="2" pos="12" show="0x0800" value="0800"/>
  </proto>
  <proto name="ip" showname="Internet Protocol, Src: 192.168.0.7 (192.168.0.7), Dst: 74.125.19.147 (74.125.19.147)" size="20" pos="14">
    <field name="ip.version" showname="Version: 4" size="1" pos="14" show="4" value="45"/>
    <field name="ip.hdr_len" showname="Header length: 20 bytes" size="1" pos="14" show="20" value="45"/>
    <field name="ip.dsfield" showname="Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00)" size="1" pos="15" show="0" value="00">
      <field name="ip.dsfield.dscp" showname="0000 00.. = Differentiated Services Codepoint: Default (0x00)" size="1" pos="15" show="0x00" value="0" unmaskedvalue="00"/>
      <field name="ip.dsfield.ect" showname=".... ..0. = ECN-Capable Transport (ECT): 0" size="1" pos="15" show="0" value="0" unmaskedvalue="00"/>
      <field name="ip.dsfield.ce" showname=".... ...0 = ECN-CE: 0" size="1" pos="15" show="0" value="0" unmaskedvalue="00"/>
    </field>
    <field name="ip.len" showname="Total Length: 60" size="2" pos="16" show="60" value="003c"/>
    <field name="ip.id" showname="Identification: 0x84c6 (33990)" size="2" pos="18" show="0x84c6" value="84c6"/>
    <field name="ip.flags" showname="Flags: 0x00" size="1" pos="20" show="0x00" value="00">
      <field name="ip.flags.rb" showname="0... = Reserved bit: Not set" size="1" pos="20" show="0" value="0" unmaskedvalue="00"/>
      <field name="ip.flags.df" showname=".0.. = Don't fragment: Not set" size="1" pos="20" show="0" value="0" unmaskedvalue="00"/>
      <field name="ip.flags.mf" showname="..0. = More fragments: Not set" size="1" pos="20" show="0" value="0" unmaskedvalue="00"/>
    </field>
    <field name="ip.frag_offset" showname="Fragment offset: 0" size="2" pos="20" show="0" value="0000"/>
    <field name="ip.ttl" showname="Time to live: 128" size="1" pos="22" show="128" value="80"/>
    <field name="ip.proto" showname="Protocol: ICMP (0x01)" size="1" pos="23" show="0x01" value="01"/>
    <field name="ip.checksum" showname="Header checksum: 0x973b [correct]" size="2" pos="24" show="0x973b" value="973b">
      <field name="ip.checksum_good" showname="Good: True" size="2" pos="24" show="1" value="973b"/>
      <field name="ip.checksum_bad" showname="Bad : False" size="2" pos="24" show="0" value="973b"/>
    </field>
    <field name="ip.src" showname="Source: 192.168.0.7 (192.168.0.7)" size="4" pos="26" show="192.168.0.7" value="c0a80007"/>
    <field name="ip.addr" showname="Source or Destination Address: 192.168.0.7 (192.168.0.7)" hide="yes" size="4" pos="26" show="192.168.0.7" value="c0a80007"/>
    <field name="ip.src_host" showname="Source Host: 192.168.0.7" hide="yes" size="4" pos="26" show="192.168.0.7" value="c0a80007"/>
    <field name="ip.host" showname="Source or Destination Host: 192.168.0.7" hide="yes" size="4" pos="26" show="192.168.0.7" value="c0a80007"/>
    <field name="ip.dst" showname="Destination: 74.125.19.147 (74.125.19.147)" size="4" pos="30" show="74.125.19.147" value="4a7d1393"/>
    <field name="ip.addr" showname="Source or Destination Address: 74.125.19.147 (74.125.19.147)" hide="yes" size="4" pos="30" show="74.125.19.147" value="4a7d1393"/>
    <field name="ip.dst_host" showname="Destination Host: 74.125.19.147" hide="yes" size="4" pos="30" show="74.125.19.147" value="4a7d1393"/>
    <field name="ip.host" showname="Source or Destination Host: 74.125.19.147" hide="yes" size="4" pos="30" show="74.125.19.147" value="4a7d1393"/>
  </proto>
  <proto name="icmp" showname="Internet Control Message Protocol" size="40" pos="34">
    <field name="icmp.type" showname="Type: 8 (Echo (ping) request)" size="1" pos="34" show="8" value="08"/>
    <field name="icmp.code" showname="Code: 0 ()" size="1" pos="35" show="0x00" value="00"/>
    <field name="icmp.checksum" showname="Checksum: 0x415c [correct]" size="2" pos="36" show="0x415c" value="415c"/>
    <field name="icmp.ident" showname="Identifier: 0x0200" size="2" pos="38" show="0x0200" value="0200"/>
    <field name="icmp.seq" showname="Sequence number: 2560 (0x0a00)" size="2" pos="40" show="2560" value="0a00"/>
    <field name="data" value="6162636465666768696a6b6c6d6e6f7071727374757677616263646566676869"/>
      <field name="data.data" showname="Data: 6162636465666768696A6B6C6D6E6F707172737475767761..." size="32" pos="42" show="61:62:63:64:65:66:67:68:69:6a:6b:6c:6d:6e:6f:70:71:72:73:74:75:76:77:61:62:63:64:65:66:67:68:69" value="6162636465666768696a6b6c6d6e6f7071727374757677616263646566676869"/>
      </proto>
</packet>

<packet>
  <proto name="geninfo" pos="0" showname="General information" size="74">
    <field name="num" pos="0" show="2" showname="Number" value="2" size="74"/>
    <field name="len" pos="0" show="74" showname="Packet Length" value="4a" size="74"/>
    <field name="caplen" pos="0" show="74" showname="Captured Length" value="4a" size="74"/>
    <field name="timestamp" pos="0" show="Jan  8, 2009 10:14:58.152631000" showname="Captured Time" value="1231373698.152631000" size="74"/>
  </proto>
  <proto name="frame" showname="Frame 2 (74 bytes on wire, 74 bytes captured)" size="74" pos="0">
    <field name="frame.time" showname="Arrival Time: Jan  8, 2009 10:14:58.152631000" size="0" pos="0" show="Jan  8, 2009 10:14:58.152631000"/>
    <field name="frame.time_delta" showname="Time delta from previous captured frame: 0.181465000 seconds" size="0" pos="0" show="0.181465000"/>
    <field name="frame.time_delta_displayed" showname="Time delta from previous displayed frame: 0.181465000 seconds" size="0" pos="0" show="0.181465000"/>
    <field name="frame.time_relative" showname="Time since reference or first frame: 0.181465000 seconds" size="0" pos="0" show="0.181465000"/>
    <field name="frame.number" showname="Frame Number: 2" size="0" pos="0" show="2"/>
    <field name="frame.pkt_len" showname="Packet Length: 74 bytes" hide="yes" size="0" pos="0" show="74"/>
    <field name="frame.len" showname="Frame Length: 74 bytes" size="0" pos="0" show="74"/>
    <field name="frame.cap_len" showname="Capture Length: 74 bytes" size="0" pos="0" show="74"/>
    <field name="frame.marked" showname="Frame is marked: False" size="0" pos="0" show="0"/>
    <field name="frame.protocols" showname="Protocols in frame: eth:ip:icmp:data" size="0" pos="0" show="eth:ip:icmp:data"/>
  </proto>
  <proto name="eth" showname="Ethernet II, Src: Netgear_ea:06:78 (00:09:5b:ea:06:78), Dst: Intel_28:c7:f7 (00:18:de:28:c7:f7)" size="14" pos="0">
    <field name="eth.dst" showname="Destination: Intel_28:c7:f7 (00:18:de:28:c7:f7)" size="6" pos="0" show="00:18:de:28:c7:f7" value="0018de28c7f7">
      <field name="eth.addr" showname="Address: Intel_28:c7:f7 (00:18:de:28:c7:f7)" size="6" pos="0" show="00:18:de:28:c7:f7" value="0018de28c7f7"/>
      <field name="eth.ig" showname=".... ...0 .... .... .... .... = IG bit: Individual address (unicast)" size="3" pos="0" show="0" value="0" unmaskedvalue="0018de"/>
      <field name="eth.lg" showname=".... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)" size="3" pos="0" show="0" value="0" unmaskedvalue="0018de"/>
    </field>
    <field name="eth.src" showname="Source: Netgear_ea:06:78 (00:09:5b:ea:06:78)" size="6" pos="6" show="00:09:5b:ea:06:78" value="00095bea0678">
      <field name="eth.addr" showname="Address: Netgear_ea:06:78 (00:09:5b:ea:06:78)" size="6" pos="6" show="00:09:5b:ea:06:78" value="00095bea0678"/>
      <field name="eth.ig" showname=".... ...0 .... .... .... .... = IG bit: Individual address (unicast)" size="3" pos="6" show="0" value="0" unmaskedvalue="00095b"/>
      <field name="eth.lg" showname=".... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)" size="3" pos="6" show="0" value="0" unmaskedvalue="00095b"/>
    </field>
    <field name="eth.type" showname="Type: IP (0x0800)" size="2" pos="12" show="0x0800" value="0800"/>
  </proto>
  <proto name="ip" showname="Internet Protocol, Src: 74.125.19.147 (74.125.19.147), Dst: 192.168.0.7 (192.168.0.7)" size="20" pos="14">
    <field name="ip.version" showname="Version: 4" size="1" pos="14" show="4" value="45"/>
    <field name="ip.hdr_len" showname="Header length: 20 bytes" size="1" pos="14" show="20" value="45"/>
    <field name="ip.dsfield" showname="Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00)" size="1" pos="15" show="0" value="00">
      <field name="ip.dsfield.dscp" showname="0000 00.. = Differentiated Services Codepoint: Default (0x00)" size="1" pos="15" show="0x00" value="0" unmaskedvalue="00"/>
      <field name="ip.dsfield.ect" showname=".... ..0. = ECN-Capable Transport (ECT): 0" size="1" pos="15" show="0" value="0" unmaskedvalue="00"/>
      <field name="ip.dsfield.ce" showname=".... ...0 = ECN-CE: 0" size="1" pos="15" show="0" value="0" unmaskedvalue="00"/>
    </field>
    <field name="ip.len" showname="Total Length: 60" size="2" pos="16" show="60" value="003c"/>
    <field name="ip.id" showname="Identification: 0x57d9 (22489)" size="2" pos="18" show="0x57d9" value="57d9"/>
    <field name="ip.flags" showname="Flags: 0x00" size="1" pos="20" show="0x00" value="00">
      <field name="ip.flags.rb" showname="0... = Reserved bit: Not set" size="1" pos="20" show="0" value="0" unmaskedvalue="00"/>
      <field name="ip.flags.df" showname=".0.. = Don't fragment: Not set" size="1" pos="20" show="0" value="0" unmaskedvalue="00"/>
      <field name="ip.flags.mf" showname="..0. = More fragments: Not set" size="1" pos="20" show="0" value="0" unmaskedvalue="00"/>
    </field>
    <field name="ip.frag_offset" showname="Fragment offset: 0" size="2" pos="20" show="0" value="0000"/>
    <field name="ip.ttl" showname="Time to live: 239" size="1" pos="22" show="239" value="ef"/>
    <field name="ip.proto" showname="Protocol: ICMP (0x01)" size="1" pos="23" show="0x01" value="01"/>
    <field name="ip.checksum" showname="Header checksum: 0x5528 [correct]" size="2" pos="24" show="0x5528" value="5528">
      <field name="ip.checksum_good" showname="Good: True" size="2" pos="24" show="1" value="5528"/>
      <field name="ip.checksum_bad" showname="Bad : False" size="2" pos="24" show="0" value="5528"/>
    </field>
    <field name="ip.src" showname="Source: 74.125.19.147 (74.125.19.147)" size="4" pos="26" show="74.125.19.147" value="4a7d1393"/>
    <field name="ip.addr" showname="Source or Destination Address: 74.125.19.147 (74.125.19.147)" hide="yes" size="4" pos="26" show="74.125.19.147" value="4a7d1393"/>
    <field name="ip.src_host" showname="Source Host: 74.125.19.147" hide="yes" size="4" pos="26" show="74.125.19.147" value="4a7d1393"/>
    <field name="ip.host" showname="Source or Destination Host: 74.125.19.147" hide="yes" size="4" pos="26" show="74.125.19.147" value="4a7d1393"/>
    <field name="ip.dst" showname="Destination: 192.168.0.7 (192.168.0.7)" size="4" pos="30" show="192.168.0.7" value="c0a80007"/>
    <field name="ip.addr" showname="Source or Destination Address: 192.168.0.7 (192.168.0.7)" hide="yes" size="4" pos="30" show="192.168.0.7" value="c0a80007"/>
    <field name="ip.dst_host" showname="Destination Host: 192.168.0.7" hide="yes" size="4" pos="30" show="192.168.0.7" value="c0a80007"/>
    <field name="ip.host" showname="Source or Destination Host: 192.168.0.7" hide="yes" size="4" pos="30" show="192.168.0.7" value="c0a80007"/>
  </proto>
  <proto name="icmp" showname="Internet Control Message Protocol" size="40" pos="34">
    <field name="icmp.type" showname="Type: 0 (Echo (ping) reply)" size="1" pos="34" show="0" value="00"/>
    <field name="icmp.code" showname="Code: 0 ()" size="1" pos="35" show="0x00" value="00"/>
    <field name="icmp.checksum" showname="Checksum: 0x495c [correct]" size="2" pos="36" show="0x495c" value="495c"/>
    <field name="icmp.ident" showname="Identifier: 0x0200" size="2" pos="38" show="0x0200" value="0200"/>
    <field name="icmp.seq" showname="Sequence number: 2560 (0x0a00)" size="2" pos="40" show="2560" value="0a00"/>
    <field name="data" value="6162636465666768696a6b6c6d6e6f7071727374757677616263646566676869"/>
      <field name="data.data" showname="Data: 6162636465666768696A6B6C6D6E6F707172737475767761..." size="32" pos="42" show="61:62:63:64:65:66:67:68:69:6a:6b:6c:6d:6e:6f:70:71:72:73:74:75:76:77:61:62:63:64:65:66:67:68:69" value="6162636465666768696a6b6c6d6e6f7071727374757677616263646566676869"/>
      </proto>
</packet>

<packet>
  <proto name="geninfo" pos="0" showname="General information" size="74">
    <field name="num" pos="0" show="3" showname="Number" value="3" size="74"/>
    <field name="len" pos="0" show="74" showname="Packet Length" value="4a" size="74"/>
    <field name="caplen" pos="0" show="74" showname="Captured Length" value="4a" size="74"/>
    <field name="timestamp" pos="0" show="Jan  8, 2009 10:15:07.868765000" showname="Captured Time" value="1231373707.868765000" size="74"/>
  </proto>
  <proto name="frame" showname="Frame 3 (74 bytes on wire, 74 bytes captured)" size="74" pos="0">
    <field name="frame.time" showname="Arrival Time: Jan  8, 2009 10:15:07.868765000" size="0" pos="0" show="Jan  8, 2009 10:15:07.868765000"/>
    <field name="frame.time_delta" showname="Time delta from previous captured frame: 9.716134000 seconds" size="0" pos="0" show="9.716134000"/>
    <field name="frame.time_delta_displayed" showname="Time delta from previous displayed frame: 9.716134000 seconds" size="0" pos="0" show="9.716134000"/>
    <field name="frame.time_relative" showname="Time since reference or first frame: 9.897599000 seconds" size="0" pos="0" show="9.897599000"/>
    <field name="frame.number" showname="Frame Number: 3" size="0" pos="0" show="3"/>
    <field name="frame.pkt_len" showname="Packet Length: 74 bytes" hide="yes" size="0" pos="0" show="74"/>
    <field name="frame.len" showname="Frame Length: 74 bytes" size="0" pos="0" show="74"/>
    <field name="frame.cap_len" showname="Capture Length: 74 bytes" size="0" pos="0" show="74"/>
    <field name="frame.marked" showname="Frame is marked: False" size="0" pos="0" show="0"/>
    <field name="frame.protocols" showname="Protocols in frame: eth:ip:icmp:data" size="0" pos="0" show="eth:ip:icmp:data"/>
  </proto>
  <proto name="eth" showname="Ethernet II, Src: Intel_28:c7:f7 (00:18:de:28:c7:f7), Dst: Netgear_ea:06:78 (00:09:5b:ea:06:78)" size="14" pos="0">
    <field name="eth.dst" showname="Destination: Netgear_ea:06:78 (00:09:5b:ea:06:78)" size="6" pos="0" show="00:09:5b:ea:06:78" value="00095bea0678">
      <field name="eth.addr" showname="Address: Netgear_ea:06:78 (00:09:5b:ea:06:78)" size="6" pos="0" show="00:09:5b:ea:06:78" value="00095bea0678"/>
      <field name="eth.ig" showname=".... ...0 .... .... .... .... = IG bit: Individual address (unicast)" size="3" pos="0" show="0" value="0" unmaskedvalue="00095b"/>
      <field name="eth.lg" showname=".... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)" size="3" pos="0" show="0" value="0" unmaskedvalue="00095b"/>
    </field>
    <field name="eth.src" showname="Source: Intel_28:c7:f7 (00:18:de:28:c7:f7)" size="6" pos="6" show="00:18:de:28:c7:f7" value="0018de28c7f7">
      <field name="eth.addr" showname="Address: Intel_28:c7:f7 (00:18:de:28:c7:f7)" size="6" pos="6" show="00:18:de:28:c7:f7" value="0018de28c7f7"/>
      <field name="eth.ig" showname=".... ...0 .... .... .... .... = IG bit: Individual address (unicast)" size="3" pos="6" show="0" value="0" unmaskedvalue="0018de"/>
      <field name="eth.lg" showname=".... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)" size="3" pos="6" show="0" value="0" unmaskedvalue="0018de"/>
    </field>
    <field name="eth.type" showname="Type: IP (0x0800)" size="2" pos="12" show="0x0800" value="0800"/>
  </proto>
  <proto name="ip" showname="Internet Protocol, Src: 192.168.0.7 (192.168.0.7), Dst: 74.125.19.147 (74.125.19.147)" size="20" pos="14">
    <field name="ip.version" showname="Version: 4" size="1" pos="14" show="4" value="45"/>
    <field name="ip.hdr_len" showname="Header length: 20 bytes" size="1" pos="14" show="20" value="45"/>
    <field name="ip.dsfield" showname="Differentiated Services Field: 0x88 (DSCP 0x22: Assured Forwarding 41; ECN: 0x00)" size="1" pos="15" show="136" value="88">
      <field name="ip.dsfield.dscp" showname="1000 10.. = Differentiated Services Codepoint: Assured Forwarding 41 (0x22)" size="1" pos="15" show="0x22" value="22" unmaskedvalue="88"/>
      <field name="ip.dsfield.ect" showname=".... ..0. = ECN-Capable Transport (ECT): 0" size="1" pos="15" show="0" value="0" unmaskedvalue="88"/>
      <field name="ip.dsfield.ce" showname=".... ...0 = ECN-CE: 0" size="1" pos="15" show="0" value="0" unmaskedvalue="88"/>
    </field>
    <field name="ip.len" showname="Total Length: 60" size="2" pos="16" show="60" value="003c"/>
    <field name="ip.id" showname="Identification: 0x8519 (34073)" size="2" pos="18" show="0x8519" value="8519"/>
    <field name="ip.flags" showname="Flags: 0x00" size="1" pos="20" show="0x00" value="00">
      <field name="ip.flags.rb" showname="0... = Reserved bit: Not set" size="1" pos="20" show="0" value="0" unmaskedvalue="00"/>
      <field name="ip.flags.df" showname=".0.. = Don't fragment: Not set" size="1" pos="20" show="0" value="0" unmaskedvalue="00"/>
      <field name="ip.flags.mf" showname="..0. = More fragments: Not set" size="1" pos="20" show="0" value="0" unmaskedvalue="00"/>
    </field>
    <field name="ip.frag_offset" showname="Fragment offset: 0" size="2" pos="20" show="0" value="0000"/>
    <field name="ip.ttl" showname="Time to live: 128" size="1" pos="22" show="128" value="80"/>
    <field name="ip.proto" showname="Protocol: ICMP (0x01)" size="1" pos="23" show="0x01" value="01"/>
    <field name="ip.checksum" showname="Header checksum: 0x9660 [correct]" size="2" pos="24" show="0x9660" value="9660">
      <field name="ip.checksum_good" showname="Good: True" size="2" pos="24" show="1" value="9660"/>
      <field name="ip.checksum_bad" showname="Bad : False" size="2" pos="24" show="0" value="9660"/>
    </field>
    <field name="ip.src" showname="Source: 192.168.0.7 (192.168.0.7)" size="4" pos="26" show="192.168.0.7" value="c0a80007"/>
    <field name="ip.addr" showname="Source or Destination Address: 192.168.0.7 (192.168.0.7)" hide="yes" size="4" pos="26" show="192.168.0.7" value="c0a80007"/>
    <field name="ip.src_host" showname="Source Host: 192.168.0.7" hide="yes" size="4" pos="26" show="192.168.0.7" value="c0a80007"/>
    <field name="ip.host" showname="Source or Destination Host: 192.168.0.7" hide="yes" size="4" pos="26" show="192.168.0.7" value="c0a80007"/>
    <field name="ip.dst" showname="Destination: 74.125.19.147 (74.125.19.147)" size="4" pos="30" show="74.125.19.147" value="4a7d1393"/>
    <field name="ip.addr" showname="Source or Destination Address: 74.125.19.147 (74.125.19.147)" hide="yes" size="4" pos="30" show="74.125.19.147" value="4a7d1393"/>
    <field name="ip.dst_host" showname="Destination Host: 74.125.19.147" hide="yes" size="4" pos="30" show="74.125.19.147" value="4a7d1393"/>
    <field name="ip.host" showname="Source or Destination Host: 74.125.19.147" hide="yes" size="4" pos="30" show="74.125.19.147" value="4a7d1393"/>
  </proto>
  <proto name="icmp" showname="Internet Control Message Protocol" size="40" pos="34">
    <field name="icmp.type" showname="Type: 8 (Echo (ping) request)" size="1" pos="34" show="8" value="08"/>
    <field name="icmp.code" showname="Code: 0 ()" size="1" pos="35" show="0x00" value="00"/>
    <field name="icmp.checksum" showname="Checksum: 0x405c [correct]" size="2" pos="36" show="0x405c" value="405c"/>
    <field name="icmp.ident" showname="Identifier: 0x0200" size="2" pos="38" show="0x0200" value="0200"/>
    <field name="icmp.seq" showname="Sequence number: 2816 (0x0b00)" size="2" pos="40" show="2816" value="0b00"/>
    <field name="data" value="6162636465666768696a6b6c6d6e6f7071727374757677616263646566676869"/>
      <field name="data.data" showname="Data: 6162636465666768696A6B6C6D6E6F707172737475767761..." size="32" pos="42" show="61:62:63:64:65:66:67:68:69:6a:6b:6c:6d:6e:6f:70:71:72:73:74:75:76:77:61:62:63:64:65:66:67:68:69" value="6162636465666768696a6b6c6d6e6f7071727374757677616263646566676869"/>
      </proto>
</packet>

<packet>
  <proto name="geninfo" pos="0" showname="General information" size="74">
    <field name="num" pos="0" show="4" showname="Number" value="4" size="74"/>
    <field name="len" pos="0" show="74" showname="Packet Length" value="4a" size="74"/>
    <field name="caplen" pos="0" show="74" showname="Captured Length" value="4a" size="74"/>
    <field name="timestamp" pos="0" show="Jan  8, 2009 10:15:08.050934000" showname="Captured Time" value="1231373708.050934000" size="74"/>
  </proto>
  <proto name="frame" showname="Frame 4 (74 bytes on wire, 74 bytes captured)" size="74" pos="0">
    <field name="frame.time" showname="Arrival Time: Jan  8, 2009 10:15:08.050934000" size="0" pos="0" show="Jan  8, 2009 10:15:08.050934000"/>
    <field name="frame.time_delta" showname="Time delta from previous captured frame: 0.182169000 seconds" size="0" pos="0" show="0.182169000"/>
    <field name="frame.time_delta_displayed" showname="Time delta from previous displayed frame: 0.182169000 seconds" size="0" pos="0" show="0.182169000"/>
    <field name="frame.time_relative" showname="Time since reference or first frame: 10.079768000 seconds" size="0" pos="0" show="10.079768000"/>
    <field name="frame.number" showname="Frame Number: 4" size="0" pos="0" show="4"/>
    <field name="frame.pkt_len" showname="Packet Length: 74 bytes" hide="yes" size="0" pos="0" show="74"/>
    <field name="frame.len" showname="Frame Length: 74 bytes" size="0" pos="0" show="74"/>
    <field name="frame.cap_len" showname="Capture Length: 74 bytes" size="0" pos="0" show="74"/>
    <field name="frame.marked" showname="Frame is marked: False" size="0" pos="0" show="0"/>
    <field name="frame.protocols" showname="Protocols in frame: eth:ip:icmp:data" size="0" pos="0" show="eth:ip:icmp:data"/>
  </proto>
  <proto name="eth" showname="Ethernet II, Src: Netgear_ea:06:78 (00:09:5b:ea:06:78), Dst: Intel_28:c7:f7 (00:18:de:28:c7:f7)" size="14" pos="0">
    <field name="eth.dst" showname="Destination: Intel_28:c7:f7 (00:18:de:28:c7:f7)" size="6" pos="0" show="00:18:de:28:c7:f7" value="0018de28c7f7">
      <field name="eth.addr" showname="Address: Intel_28:c7:f7 (00:18:de:28:c7:f7)" size="6" pos="0" show="00:18:de:28:c7:f7" value="0018de28c7f7"/>
      <field name="eth.ig" showname=".... ...0 .... .... .... .... = IG bit: Individual address (unicast)" size="3" pos="0" show="0" value="0" unmaskedvalue="0018de"/>
      <field name="eth.lg" showname=".... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)" size="3" pos="0" show="0" value="0" unmaskedvalue="0018de"/>
    </field>
    <field name="eth.src" showname="Source: Netgear_ea:06:78 (00:09:5b:ea:06:78)" size="6" pos="6" show="00:09:5b:ea:06:78" value="00095bea0678">
      <field name="eth.addr" showname="Address: Netgear_ea:06:78 (00:09:5b:ea:06:78)" size="6" pos="6" show="00:09:5b:ea:06:78" value="00095bea0678"/>
      <field name="eth.ig" showname=".... ...0 .... .... .... .... = IG bit: Individual address (unicast)" size="3" pos="6" show="0" value="0" unmaskedvalue="00095b"/>
      <field name="eth.lg" showname=".... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)" size="3" pos="6" show="0" value="0" unmaskedvalue="00095b"/>
    </field>
    <field name="eth.type" showname="Type: IP (0x0800)" size="2" pos="12" show="0x0800" value="0800"/>
  </proto>
  <proto name="ip" showname="Internet Protocol, Src: 74.125.19.147 (74.125.19.147), Dst: 192.168.0.7 (192.168.0.7)" size="20" pos="14">
    <field name="ip.version" showname="Version: 4" size="1" pos="14" show="4" value="45"/>
    <field name="ip.hdr_len" showname="Header length: 20 bytes" size="1" pos="14" show="20" value="45"/>
    <field name="ip.dsfield" showname="Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00)" size="1" pos="15" show="0" value="00">
      <field name="ip.dsfield.dscp" showname="0000 00.. = Differentiated Services Codepoint: Default (0x00)" size="1" pos="15" show="0x00" value="0" unmaskedvalue="00"/>
      <field name="ip.dsfield.ect" showname=".... ..0. = ECN-Capable Transport (ECT): 0" size="1" pos="15" show="0" value="0" unmaskedvalue="00"/>
      <field name="ip.dsfield.ce" showname=".... ...0 = ECN-CE: 0" size="1" pos="15" show="0" value="0" unmaskedvalue="00"/>
    </field>
    <field name="ip.len" showname="Total Length: 60" size="2" pos="16" show="60" value="003c"/>
    <field name="ip.id" showname="Identification: 0x57db (22491)" size="2" pos="18" show="0x57db" value="57db"/>
    <field name="ip.flags" showname="Flags: 0x00" size="1" pos="20" show="0x00" value="00">
      <field name="ip.flags.rb" showname="0... = Reserved bit: Not set" size="1" pos="20" show="0" value="0" unmaskedvalue="00"/>
      <field name="ip.flags.df" showname=".0.. = Don't fragment: Not set" size="1" pos="20" show="0" value="0" unmaskedvalue="00"/>
      <field name="ip.flags.mf" showname="..0. = More fragments: Not set" size="1" pos="20" show="0" value="0" unmaskedvalue="00"/>
    </field>
    <field name="ip.frag_offset" showname="Fragment offset: 0" size="2" pos="20" show="0" value="0000"/>
    <field name="ip.ttl" showname="Time to live: 239" size="1" pos="22" show="239" value="ef"/>
    <field name="ip.proto" showname="Protocol: ICMP (0x01)" size="1" pos="23" show="0x01" value="01"/>
    <field name="ip.checksum" showname="Header checksum: 0x5526 [correct]" size="2" pos="24" show="0x5526" value="5526">
      <field name="ip.checksum_good" showname="Good: True" size="2" pos="24" show="1" value="5526"/>
      <field name="ip.checksum_bad" showname="Bad : False" size="2" pos="24" show="0" value="5526"/>
    </field>
    <field name="ip.src" showname="Source: 74.125.19.147 (74.125.19.147)" size="4" pos="26" show="74.125.19.147" value="4a7d1393"/>
    <field name="ip.addr" showname="Source or Destination Address: 74.125.19.147 (74.125.19.147)" hide="yes" size="4" pos="26" show="74.125.19.147" value="4a7d1393"/>
    <field name="ip.src_host" showname="Source Host: 74.125.19.147" hide="yes" size="4" pos="26" show="74.125.19.147" value="4a7d1393"/>
    <field name="ip.host" showname="Source or Destination Host: 74.125.19.147" hide="yes" size="4" pos="26" show="74.125.19.147" value="4a7d1393"/>
    <field name="ip.dst" showname="Destination: 192.168.0.7 (192.168.0.7)" size="4" pos="30" show="192.168.0.7" value="c0a80007"/>
    <field name="ip.addr" showname="Source or Destination Address: 192.168.0.7 (192.168.0.7)" hide="yes" size="4" pos="30" show="192.168.0.7" value="c0a80007"/>
    <field name="ip.dst_host" showname="Destination Host: 192.168.0.7" hide="yes" size="4" pos="30" show="192.168.0.7" value="c0a80007"/>
    <field name="ip.host" showname="Source or Destination Host: 192.168.0.7" hide="yes" size="4" pos="30" show="192.168.0.7" value="c0a80007"/>
  </proto>
  <proto name="icmp" showname="Internet Control Message Protocol" size="40" pos="34">
    <field name="icmp.type" showname="Type: 0 (Echo (ping) reply)" size="1" pos="34" show="0" value="00"/>
    <field name="icmp.code" showname="Code: 0 ()" size="1" pos="35" show="0x00" value="00"/>
    <field name="icmp.checksum" showname="Checksum: 0x485c [correct]" size="2" pos="36" show="0x485c" value="485c"/>
    <field name="icmp.ident" showname="Identifier: 0x0200" size="2" pos="38" show="0x0200" value="0200"/>
    <field name="icmp.seq" showname="Sequence number: 2816 (0x0b00)" size="2" pos="40" show="2816" value="0b00"/>
    <field name="data" value="6162636465666768696a6b6c6d6e6f7071727374757677616263646566676869"/>
      <field name="data.data" showname="Data: 6162636465666768696A6B6C6D6E6F707172737475767761..." size="32" pos="42" show="61:62:63:64:65:66:67:68:69:6a:6b:6c:6d:6e:6f:70:71:72:73:74:75:76:77:61:62:63:64:65:66:67:68:69" value="6162636465666768696a6b6c6d6e6f7071727374757677616263646566676869"/>
      </proto>
</packet>
</pdml>

January 20, 2009

DSCP to Type of Service Mappings

Filed under: Code, Network — Tags: , , , — networknerd @ 11:45 am

When working with quality of service configurations you’ll inevitably come across the need to perform packet markings with DSCP.  With routers this is generally fairly simple.  Performing the same function on a host is not always that simple.  All the socket API’s were designed around type of service (ToS),as defined in RFC791, rather than DSCP as defined in RFC2474.

If you’re in a hurry, the conversion is simply ToS = DSCP * 4. If you have the time the rfc’s are full of interesting information. The DSCP field with the DS field contains six bits allowing for 64 possible codepoint values. RFC2474 defines 3 pools of DSCP values, one for standardised use and the other two for local/experimental use. The standardised pool has the least significant bit set to 0, which means only the even numbers from 0 to 62 are used. A cheat sheet with the standardised DSCP values and equivalent IP precedence and ToS values can be found here.

We can test the ToS/DSCP mapping using the ping program and specifying a ToS byte value. Using the windows ping program we specify the ToS byte as a numeric argument to the -v command line switch. In this example we specify the the ToS byte as 136 which corresponds to a DSCP value of 34  or AF41.

ping -n 1 -v 136 http://www.google.com

Performing a similar test for tcp connection requires a little bit of coding effort. Listing 1 shows some c# code to do a simple get request to http://www.google.com.au,  using the SetSocketOption function to set the ToS byte to 136.  The wireshark output for both tests is shown below.  The  lua script shown in listing 2 was used to extract the diffserv field and dscp values while running the capture with Tshark. It is worth noting that even though the socketoption is set prior to the connection, no dscp values are set on the two packets from the client during the TCP three way handshake (frame 5 and 7 below).

tshark  -X lua_script:getdscp.lua -i 2 host http://www.google.com.au
Frame #1    Diffserv Field: 136    DSCP: 34
192.168.0.7 -> 74.125.19.103 ICMP Echo (ping) request

Frame #2    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  ICMP Echo (ping) reply

Frame #3    Diffserv Field: 136    DSCP: 34
192.168.0.7 -> 74.125.19.103 ICMP Echo (ping) request

Frame #4    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  ICMP Echo (ping) reply

Frame #5    Diffserv Field: 0    DSCP: 0
192.168.0.7 -> 74.125.19.103 TCP linx > http [SYN] Seq=0 Win=16384 Len=0 MSS=1260

Frame #6    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  TCP http > linx [SYN, ACK] Seq=0 Ack=1 Win=5720 Len=0 MSS=1430

Frame #7    Diffserv Field: 0    DSCP: 0
192.168.0.7 -> 74.125.19.103 TCP linx > http [ACK] Seq=1 Ack=1 Win=17640 Len=0

Frame #8    Diffserv Field: 136    DSCP: 34
192.168.0.7 -> 74.125.19.103 HTTP GET / HTTP/1.0

Frame #9    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  TCP http > linx [ACK] Seq=1 Ack=41 Win=5720 Len=0

Frame #10    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  TCP [TCP segment of a reassembled PDU]

Frame #11    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  TCP [TCP segment of a reassembled PDU]

Frame #12    Diffserv Field: 136    DSCP: 34
192.168.0.7 -> 74.125.19.103 TCP linx > http [ACK] Seq=41 Ack=2521 Win=17640 Len=0

Frame #13    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  TCP [TCP segment of a reassembled PDU]

Frame #14    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  TCP [TCP segment of a reassembled PDU]

Frame #15    Diffserv Field: 136    DSCP: 34
192.168.0.7 -> 74.125.19.103 TCP linx > http [ACK] Seq=41 Ack=5041 Win=17640 Len=0

Frame #16    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  TCP [TCP segment of a reassembled PDU]

Frame #17    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  HTTP HTTP/1.0 200 OK  (text/html)

Frame #18    Diffserv Field: 136    DSCP: 34
192.168.0.7 -> 74.125.19.103 TCP linx > http [ACK] Seq=41 Ack=6611 Win=17640 Len=0

Frame #19    Diffserv Field: 136    DSCP: 34
192.168.0.7 -> 74.125.19.103 TCP linx > http [FIN, ACK] Seq=41 Ack=6611 Win=17640 Len=0

Frame #20    Diffserv Field: 0    DSCP: 0
74.125.19.103 -> 192.168.0.7  TCP http > linx [ACK] Seq=6611 Ack=42 Win=5720 Len=0
Listing  1

using System;
using System.Text;
using System.Net.Sockets;

namespace tcptos
{
	class Program
	{
		public static void Main(string[] args)
		{
			Console.WriteLine("Testing DSCP packet marking.Wireshark should already be running!\n");

			TcpClient cli = new TcpClient();
			cli.Client.SetSocketOption(SocketOptionLevel.IP,
			                           SocketOptionName.TypeOfService, 136);
			cli.Connect("www.google.com.au",80);
			byte[] buf = Encoding.ASCII.GetBytes("GET / HTTP/1.0\nHost: www.google.com.au\n\n");
			byte[] readbuf = new byte[4096];
			int bytesRead;
			StringBuilder response = new StringBuilder();
			NetworkStream mystream = cli.GetStream();
			mystream.Write(buf,0,buf.Length);
			do{
				bytesRead = mystream.Read(readbuf, 0, readbuf.Length);
				response.AppendFormat("{0}", Encoding.ASCII.GetString(readbuf, 0, bytesRead));
			}
			while(bytesRead > 0);
			Console.Write(response.ToString());
			Console.Write("\nPress any key to continue . . . ");
			Console.ReadKey(true);
			cli.Close();
		}
	}
}

Listing 2

local dsfield = Field.new("ip.dsfield")
local dscp = Field.new("ip.dsfield.dscp")
local fnum = Field.new("frame.number")
do
    packets = 0;
    local function init_listener()
        local tap = Listener.new("frame","ip.version == 4")

        function tap.reset()
        end
        function tap.packet(pinfo,tvb,ip)
            local fnumber = tostring(fnum())
            local diffserv = tostring(dsfield())
            local codepoint = tostring(dscp())
            local stroutput = "\nFrame #" .. fnumber .. "\tDiffserv Field: " ..
				diffserv .. "\tDSCP: " ..codepoint
            print(stroutput)
        end
        function tap.draw()

        end
    end
    init_listener()
end

January 1, 2009

Accessing Firefox 3 Discontinuous Selections with Javascript

Filed under: Code — Tags: , , — networknerd @ 1:02 pm

Firefox 3 now has the ability to highlight discontinuous sections of a web page by holding down the control key while making the selections. Very handy for note taking where you want to cut and paste only the relevant sections.

It occurred to me though that it might be useful to be able to access the individual parts of the selection.  My first guess was to use the window.getSelection() method and pass it an integer which refers to the part of the selection.  Bad guess, that just gave me all parts of the selection concatenated.  After referring to the documentation it seems that the selection object has the rangeCount property and the getRangeAt method for accessing individual parts of the selection.

I decided to use a bookmarklet as a quick and dirty way to check it out.  The code is listed below in a readable format or you can copy the whole url if you want to test it as is.

It’s worth pointing out that your mileage may vary here if your trying to extract a selection from an input control such as a text box.

javascript:
(
  function()
  {
    var sel=window.getSelection();
    var cnt=sel.rangeCount;
    var ranges=[];
    for(var i = 0; i < sel.rangeCount; i++)
    {
      ranges[i] = sel.getRangeAt(i);
      alert(ranges[i]);
    }
    alert(cnt);
  }()
);
javascript:(function(){var%20sel=window.getSelection();var%20cnt=sel.rangeCount;var%20ranges=[];for(var%20i%20=%200;%20i%20<%20sel.rangeCount;%20i++){ranges[i]%20=%20sel.getRangeAt(i);alert(ranges[i]);}alert(cnt);}());

November 23, 2008

Active Directory Account Auditing With Excel

Filed under: Code — Tags: , , , — networknerd @ 10:56 am

One of the less attractive aspects of a career in security is routine auditing.  It’s boring, but it still needs to be done.  As users leave the HR department should notify IT and the account should be disabled or set to expire on their last day in the office.  The process can go wrong at HR or in IT.

To make the audit task a little easier I came up with a VBA macro for excel. Active directory is queried for all user accounts that are not disabled by running the AD_QUERY macro.  The spreadsheet is populated with a list of all active accounts.  The CopyPW and  CopyLstLogon macros will add an additional worksheet each which contains filtered lists of accounts with passwords that don’t expire, and last logons greater than 90 days.

The need to change passwords is obvious, but the last logon timestamp being greater than 90 days is a good indicator that someone has left and there was a process failure, or that it was a test account that should have been deleted.

To use the macros just create a new spreadsheet and open the VBA editor using ALT-F11, right click on VBAPROJECT(Book1) and select insert then module from the context menu.  Copy the code from listing 1 and paste it into the new module.  Close the VBA editor and your ready to run the macros.

Hope this makes life a little easier for you if your doing the account audits.

Listing 1

Option Explicit
Const ADS_UF_ACCOUNTDISABLE = 2
Const ADS_SCOPE_SUBTREE = 2
Const ADS_UF_DONT_EXPIRE_PASSWD = 65536
Const FLD_FULLNAME = 1
Const FLD_SAM_ACCTNAME = 2
Const FLD_CREATEDATE = 3
Const FLD_PWD_LASTCHNG = 4
Const FLD_PWD_DONTEXPIRE = 5
Const FLD_UAC = 6
Const FLD_LASTLOGON = 7
Const FLD_ADSPATH = 8
Const FLD_MAX = 8
Const HEADROW = 1
Const ASCII_OFFSET = 64
Sub AD_QUERY()
Dim objUser, objLogon, objConnection, objCommand, objRecordSet
Dim strPath, strFullName, strSamAccountName
Dim intUAC, intLogonTime
Dim createdate, pwdchanged
Dim Disabled, PWDexpire, intCounter
Dim objsheet As Excel.Worksheet
Dim rngData As Excel.Range
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Properties("ADSI Flag") = 1
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection
objCommand.Properties("Page Size") = 10000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE
'Search AD Global catalog for user objects that are not disabled
objCommand.CommandText =  "<GC://dc=acme,dc=com,dc=au>;" & _
  "(&(objectClass=user)(objectCategory=person)(!userAccountControl:1.2.840.113556.1.4.803:=2));" & _
  "adspath, samAccountName; subtree"
Application.StatusBar = "Executing AD Query. Please wait..."
Set objRecordSet = objCommand.Execute
Application.StatusBar = "Populating Worksheet with data. Please wait..."
Set objsheet = Application.ActiveWorkbook.Worksheets.Add()
objsheet.Name = Format(Date, "dd-mm-yyyy") & " Raw Data"
intCounter = 2 'Initialise worksheet row counter
objsheet.Cells(HEADROW, FLD_FULLNAME).Value = "Full Name"
objsheet.Cells(HEADROW, FLD_SAM_ACCTNAME).Value = "SAM Account name"
objsheet.Cells(HEADROW, FLD_CREATEDATE).Value = "Create Date (UTC)"
objsheet.Cells(HEADROW, FLD_PWD_LASTCHNG).Value = "PWD Last Changed"
objsheet.Cells(HEADROW, FLD_PWD_DONTEXPIRE).Value = "PWD Don't Expire"
objsheet.Cells(HEADROW, FLD_UAC).Value = "UAC"
objsheet.Cells(HEADROW, FLD_LASTLOGON).Value = "LastLogonTimestamp"
objsheet.Cells(HEADROW, FLD_ADSPATH).Value = "ADSPATH"
objRecordSet.MoveFirst
Do Until objRecordSet.EOF
  strPath = objRecordSet.Fields("adspath")
'Change the global catalog path to an ldap path so that we can access
'all the attributes when binding to the object.
  strPath = Replace(strPath, "GC://", "LDAP://")
  Set objUser = GetObject(strPath) intUAC = objUser.userAccountControl
  If (intUAC And ADS_UF_DONT_EXPIRE_PASSWD) = 0 Then
    PWDexpire = False
  Else
    PWDexpire = True
  End If
  On Error Resume Next
  Err.Clear
  Set objLogon = objUser.LastLogonTimestamp
  If Err.Number <> 0 Then
    intLogonTime = 0
    Err.Clear
  Else
    intLogonTime = objLogon.HighPart * (2 ^ 32) + objLogon.LowPart
    intLogonTime = intLogonTime / (60 * 10000000)
    intLogonTime = intLogonTime / 1440
  End If
  strFullName = objUser.FullName
  If Err.Number <> 0 Then
    strFullName = ""
    Err.Clear
  End If
  createdate = objUser.whenCreated
  If Err.Number <> 0 Then
    createdate = ""
    Err.Clear
  End If
  pwdchanged = objUser.passwordLastChanged
  If Err.Number <> 0 Then
    pwdchanged = ""
    Err.Clear
  End If
  On Error GoTo 0
  strSamAccountName = objUser.SamAccountName
  objsheet  .Cells(intCounter, FLD_FULLNAME).Value = strFullName
  objsheet.Cells(intCounter, FLD_SAM_ACCTNAME).Value = strSamAccountName
  objsheet.Cells(intCounter, FLD_CREATEDATE).Value = createdate
  objsheet.Cells(intCounter, FLD_PWD_LASTCHNG).Value = pwdchanged
  objsheet.Cells(intCounter, FLD_PWD_DONTEXPIRE).Value = PWDexpire
  objsheet.Cells(intCounter, FLD_UAC).Value = intUAC
  If intLogonTime <> 0 Then
    objsheet.Cells(intCounter, FLD_LASTLOGON).Value = intLogonTime + #1/1/1601#
  Else
    objsheet.Cells(intCounter, FLD_LASTLOGON).Value = "#1/1/1601#"
  End If
  objsheet.Cells(intCounter, FLD_ADSPATH).Value = strPath
  objRecordSet.MoveNext intCounter = intCounter + 1
Loop
Set rngData = objsheet.Range("A1:" & Chr(ASCII_OFFSET + FLD_MAX) & intCounter - 1)
'if the named range already exists we need to delete is before we create it again.
'This will allow more than one audit set to be retained in the same workbook.
On Error Resume Next
ActiveWorkbook.Names("AD_DATA_SET").Delete
On Error GoTo 0
rngData.Name = "AD_DATA_SET"
rngData.Columns.AutoFit
Application.StatusBar = "Ready"
End Sub

Sub filter_lastlogon()
Dim rngData As Excel.Range
Set rngData = Range("AD_DATA_SET")
rngData.Worksheet.AutoFilterMode = False
'Filter function seems to ignore locale info so dates must be in US format
rngData.autofilter Field:=FLD_LASTLOGON, Criteria1:="=#1/1/1601#", Operator:=xlOr, _
  Criteria2:="<" & Format(Now() - 90, "mm/dd/yyyy")
End Sub

Sub filter_pwd_dontexpire()
Dim rngData As Excel.Range
Set rngData = Range("AD_DATA_SET")
rngData.Worksheet.AutoFilterMode = False
rngData.autofilter Field:=FLD_PWD_DONTEXPIRE, Criteria1:="=True"
End Sub

Sub RemoveFilter()
Dim rngData As Excel.Range
Set rngData = Range("AD_DATA_SET")
rngData.Worksheet.AutoFilterMode = False
End Sub

Sub CopyPW()
'Copies the filtered data to a new Worksheet
'Code modified from http://www.contextures.com/xlautofilter03.html#Copy
'Viewed 7/6/2007
Dim rngData As Excel.Range
Dim rng As Range
Dim rng2 As Range
Dim objsheet As Worksheet
Set rngData = Range("AD_DATA_SET")
Call filter_pwd_dontexpire
If Not rngData.Worksheet.FilterMode Then
  MsgBox "Filter Data before selecting this option", vbExclamation
  Exit Sub
End If
With rngData.Worksheet.autofilter.Range
  On Error Resume Next
  Set rng2 = .Offset(1, 0).Resize(.Rows.Count - 1, 1) _
    .SpecialCells(xlCellTypeVisible)
  On Error GoTo 0
End With
If rng2 Is Nothing
  Then MsgBox "No data to copy"
Else
  Set objsheet = Application.ActiveWorkbook.Worksheets.Add()
  objsheet.Name = Format(Date, "dd-mm-yyyy") & " Password dont expire"
  Set rng = rngData.Worksheet.autofilter.Range rng.Offset(1, 0).Resize(rng.Rows.Count - 1).Copy _
    Destination:=objsheet.Range("A2")
  objsheet.Cells(HEADROW, FLD_FULLNAME).Value = "Full Name"
  objsheet.Cells(HEADROW, FLD_SAM_ACCTNAME).Value = "SAM Account name"
  objsheet.Cells(HEADROW, FLD_CREATEDATE).Value = "Create Date (UTC)"
  objsheet.Cells(HEADROW, FLD_PWD_LASTCHNG).Value = "PWD Last Changed"
  objsheet.Cells(HEADROW, FLD_PWD_DONTEXPIRE).Value = "PWD Don't Expire"
  objsheet.Cells(HEADROW, FLD_UAC).Value = "UAC"
  objsheet.Cells(HEADROW, FLD_LASTLOGON).Value = "LastLogonTimestamp"
  objsheet.Cells(HEADROW, FLD_ADSPATH).Value = "ADSPATH"
  objsheet.Columns.AutoFit
End If
End Sub

Sub CopyLstLogon()
'Copies the filtered data to a new Worksheet
'Code modified from http://www.contextures.com/xlautofilter03.html#Copy
'Viewed 7/6/2007
Dim rngData As Excel.Range
Dim rng As Range
Dim rng2 As Range
Dim objsheet As Worksheet
Set rngData = Range("AD_DATA_SET")
Call filter_lastlogon
If Not rngData.Worksheet.FilterMode Then
  MsgBox "Filter Data before selecting this option", vbExclamation
  Exit Sub
End If
With rngData.Worksheet.autofilter.Range
  On Error Resume Next
  Set rng2 = .Offset(1, 0).Resize(.Rows.Count - 1, 1) _
    .SpecialCells(xlCellTypeVisible)
  On Error GoTo 0
End With
If rng2 Is Nothing Then
  MsgBox "No data to copy"
Else
  Set objsheet = Application.ActiveWorkbook.Worksheets.Add()
  objsheet.Name = Format(Date, "dd-mm-yyyy") & " LastLogon > 90 days"
  Set rng = rngData.Worksheet.autofilter.Range rng.Offset(1, 0).Resize(rng.Rows.Count - 1).Copy _
    Destination:=objsheet.Range("A2")
  objsheet.Cells(HEADROW, FLD_FULLNAME).Value = "Full Name"
  objsheet.Cells(HEADROW, FLD_SAM_ACCTNAME).Value = "SAM Account name"
  objsheet.Cells(HEADROW, FLD_CREATEDATE).Value = "Create Date (UTC)"
  objsheet.Cells(HEADROW, FLD_PWD_LASTCHNG).Value = "PWD Last Changed"
  objsheet.Cells(HEADROW, FLD_PWD_DONTEXPIRE).Value = "PWD Don't Expire"
  objsheet.Cells(HEADROW, FLD_UAC).Value = "UAC"
  objsheet.Cells(HEADROW, FLD_LASTLOGON).Value = "LastLogonTimestamp"
  objsheet.Cells(HEADROW, FLD_ADSPATH).Value = "ADSPATH"
  objsheet.Columns.AutoFit
End If
End Sub

October 31, 2008

Movember – Fighting Prostate Cancer

Filed under: Uncategorized — Tags: , , — networknerd @ 12:06 pm

Ok this is not a normal post for a geek blog, but statistically speaking there is a very high chance that if you’ve stumbled across this blog that you have a prostate and that you are at risk! Apologies in advance to all you geekgirls that might be offended by that statement.

Ben Smallwood, a lawyer but nonetheless a gentleman, is currently braving cruel “70’s porn star” jokes to raise funds for this worthwhile cause.  No he hasn’t “come to clean ze pool” . He’s raising money for a charity that benefits all men. Please help the cause by donating at the Movember website https://www.movember.com/au/donate/donate-details.php?action=sonsorlink&rego=1574726&country=au

More information is available at http://au.movember.com/
Movember - Sponsor Me

October 29, 2008

IOS Upgrade – %SYS-3-IMAGE_TOO_BIG

Filed under: Cisco, Network — networknerd @ 8:49 pm

I attempted an IOS upgrade on a 3845 router on the weekend and, upon reboot received this error on the console:

%SYS-3-IMAGE_TOO_BIG: ‘flash:c3845-advipservicesk9-mz.124-22.T.bin’ is too large for available memory (50954264 bytes).boot of “c3845-advipservicesk9-mz.124-22.T.bin” using boot helper “flash:c3845-advipservicesk9-mz.123-11.T5.bin” failed

The message seems self explanatory.  The image is too big for memory.  However I did do my homework and the router had the minimum 512 mb memory and 128 mb flash.  The interesting thing here is the second sentence. I had left the original image in the flash (since there was plenty of room) and used a boot system command to ensure that the new IOS was loaded. The old image was being loaded, at least partially, as a boot helper.

I thought that the boot helper came from the ROM but this indicates a second stage boot process using the first image found in flash, not the image specified in the config.  Possibilities here are that the second stage boot loader from the 12.3 image took up too much memory. Alternatively it may be possible that the boot loader has a hardcoded limit for allocating a buffer to read the image into.  I didn’t have any extra memory to test that theory.

Since the second stage boot loader was being loaded from the first available image, and we know the image is selected in dir (alphabetical) order it was a simple matter to rename the old image from c3845-advipservicesk9-mz.123-11.T5.bin to c3845-advipservicesk9-mz.128-11.T5.bin. After rebooting the image loaded perfectly.

So the moral of the story is if the image should fit in memory and you have old images in flash, you should either delete them or rename them so that they appear after the desired boot image when you execute the show flash command.

Leave a comment if you’ve struck this problem before or you know more about the boot process.

October 26, 2008

Configuring OpenLDAP for Client Certificate Authentication

Filed under: Certificates, linux, openldap — Tags: , , , — networknerd @ 12:30 pm

I wanted to test the MAC authentication bypass mechanism as an alternative to switchport configuration using snmp when re-imaging computers in an 802.1x network.   According to the Cisco documentation that requires an LDAP server to hold the MAC addresses of the computers, and an LDAP client program to add the MAC addresses and modify the group information.

Since re-imaging is an automated operation there would be no way to enter an LDAP password.  I didn’t want to hard code the password into the client or a script.  That left me with two options to investigate, certificate based authentication or kerberos. From the title of the post it should be obvious that I wasn’t brave enough to try kerberos.

Materials:

  • ADIOS 4.12 Linux Boot CD, containing OpenLDAP 2.2.13 and Cyrus SASL 2.1.19
  • Spare computer that will boot the CD.
  • Certificates – Self-signed CA certificate, server certifcate and client certificate.  See this post for more information on generating self-signed certificates.

The important configuration file for OpenLDAP is /etc/openldap/slapd.conf, as shown in listing 2.  The important lines for certificate authentication  are shown below.  Note the sasl-regexp can be difficult to get right. The cn of my client certificate contains spaces, which caused the slapd.conf to fail verification.  I tried using \s to match the spaces but eventually had to fall back to “.”

#Trusted CA certificates
TLSCACertificateFile /media/usb/ldap/Acme/cacert.pem
#Server certificate file
TLSCertificateFile /media/usb/ldap/Acme/ldap.pem
#Server certificate key file
TLSCertificateKeyFile /media/usb/ldap/Acme/ldap.pem
#Force Openldap to ask for a client certificate
TLSVerifyClient	try

#Map the certifcate dn to the openldap dn
#Note that sasl-regexp became authz-regexp in version 2.3
sasl-regexp
   cn=LDAP.Server.Manager
   cn=Manager,dc=acme,dc=com,dc=au
#set openldap logging level to debug
loglevel -1

The ldap client configuration file  is .ldaprc and is usually located in the home directory of the user.  Listing 1  shows a .ldaprc file’s contents.  Note the lines beginning with TLS specifying the acceptable CA certificates and the certificate and keyfile to be used for authentication, and SASL_MECH to specify EXTERNAL (TLS client certificate) authentication.

We can check that everything is configured correctly by performing a search.  The -ZZ option forces the use of TLS and requires it to be successful.

[adios@adios-bootcd ~]$ ldapsearch    -ZZ -h ldap.acme.com.au    -b “” -s base +
Enter PEM pass phrase:clientcertpassword
SASL/EXTERNAL authentication started
SASL username: emailAddress=ldapmanager@acme.com.au,CN=LDAP Server Manager,O=Acme Pty Ltd,L=Brisbane,ST=Queensland,C=AU
SASL SSF: 0
# extended LDIF

….
supportedSASLMechanisms: PLAIN
supportedSASLMechanisms: LOGIN
supportedSASLMechanisms: DIGEST-MD5
supportedSASLMechanisms: CRAM-MD5
supportedSASLMechanisms: EXTERNAL
subschemaSubentry: cn=Subschema

# search result
search: 3
result: 0 Success

# numResponses: 2
# numEntries: 1

Now we can attempt to add entries to the ldap database. The contents of default.ldif are shown in listing 3.

[adios@adios-bootcd ~]$ ldapadd -ZZ -h ldap.acme.com.au -f /media/usb/ldap/conf/default.ldif
Enter PEM pass phrase:
SASL/EXTERNAL authentication started
SASL username: emailAddress=ldapmanager@acme.com.au,CN=LDAP Server Manager,O=Acme Pty Ltd,L=Brisbane,ST=Queensland,C=AU
SASL SSF: 0
adding new entry “dc=acme,dc=com,dc=au”
adding new entry “cn=Manager,dc=acme,dc=com,dc=au”
adding new entry “cn=Barbara Jensen,dc=acme,dc=com,dc=au”
adding new entry “ou=MAB Segment, dc=acme,dc=com,dc=au”
adding new entry “ou=MAC Addresses, ou=MAB Segment, dc=acme,dc=com,dc=au”
adding new entry “ou=MAC Groups, ou=MAB Segment, dc=acme,dc=com,dc=au”
adding new entry “cn=acctsprn,ou=MAC Addresses, ou=MAB Segment, dc=acme, dc=com, dc=au”
adding new entry “cn=printgroup,ou=MAC Groups, ou=MAB Segment, dc=acme, dc=com,dc=au”

Listing 1 .ldaprc

#
# LDAP Defaults
#

# See ldap.conf(5) for details
# This file should be world readable but not world writable.

#SIZELIMIT    12
#TIMELIMIT    15
#DEREF        never
HOST 127.0.0.1
BASE dc=acme,dc=com,dc=au
#URI         ldaps://ldap.acme.com.au:636/

SASL_MECH   EXTERNAL
TLS_CERT    /media/usb/ldap/Acme/ldapmgr.pem
TLS_KEY     /media/usb/ldap/Acme/ldapmgrkey.pem
TLS_CACERT  /media/usb/ldap/Acme/cacert.pem

Listing 2 slapd.conf

#
# See slapd.conf(5) for details on configuration options.
# This file should NOT be world readable.
#
include		/etc/openldap/schema/core.schema
include		/etc/openldap/schema/cosine.schema
include		/etc/openldap/schema/inetorgperson.schema
include		/etc/openldap/schema/nis.schema

# Allow LDAPv2 client connections.  This is NOT the default.
allow bind_v2

# Do not enable referrals until AFTER you have a working directory
# service AND an understanding of referrals.
#referral	ldap://root.openldap.org

pidfile		/var/run/slapd.pid
argsfile	/var/run/slapd.args

# Load dynamic backend modules:
# modulepath	/usr/sbin/openldap
# moduleload	back_bdb.la
# moduleload	back_ldap.la
# moduleload	back_ldbm.la
# moduleload	back_passwd.la
# moduleload	back_shell.la

# The next three lines allow use of TLS for encrypting connections using a
# dummy test certificate which you can generate by changing to
# /usr/share/ssl/certs, running "make slapd.pem", and fixing permissions on
# slapd.pem so that the ldap user or group can read it.  Your client software
# may balk at self-signed certificates, however.
# TLSCACertificateFile /usr/share/ssl/certs/ca-bundle.crt
# TLSCertificateFile /usr/share/ssl/certs/slapd.pem
# TLSCertificateKeyFile /usr/share/ssl/certs/slapd.pem

TLSCACertificateFile /media/usb/ldap/Acme/cacert.pem
TLSCertificateFile /media/usb/ldap/Acme/ldap.pem
TLSCertificateKeyFile /media/usb/ldap/Acme/ldap.pem
TLSVerifyClient	try
# Sample security restrictions
#	Require integrity protection (prevent hijacking)
#	Require 112-bit (3DES or better) encryption for updates
#	Require 63-bit encryption for simple bind
# security ssf=1 update_ssf=112 simple_bind=64

# Sample access control policy:
#	Root DSE: allow anyone to read it
#	Subschema (sub)entry DSE: allow anyone to read it
#	Other DSEs:
#		Allow self write access
#		Allow authenticated users read access
#		Allow anonymous users to authenticate
#	Directives needed to implement policy:
# access to dn.base="" by * read
# access to dn.base="cn=Subschema" by * read
# access to *
#	by self write
#	by users read
#	by anonymous auth
#
# if no access controls are present, the default policy
# allows anyone and everyone to read anything but restricts
# updates to rootdn.  (e.g., "access to * by * read")
#
# rootdn can always read and write EVERYTHING!

#######################################################################
# ldbm and/or bdb database definitions
#######################################################################

database	bdb
suffix		"dc=acme,dc=com,dc=au"
rootdn		"cn=Manager,dc=acme,dc=com,dc=au"
# Cleartext passwords, especially for the rootdn, should
# be avoided.  See slappasswd(8) and slapd.conf(5) for details.
# Use of strong authentication encouraged.
# rootpw		secret
# rootpw		{crypt}ijFYNcSNctBYg

# The database directory MUST exist prior to running slapd AND
# should only be accessible by the slapd and slap tools.
# Mode 700 recommended.
directory	/var/lib/ldap

# Indices to maintain for this database
index objectClass                       eq,pres
index ou,cn,mail,surname,givenname      eq,pres,sub
index uidNumber,gidNumber,loginShell    eq,pres
index uid,memberUid                     eq,pres,sub
index nisMapName,nisMapEntry            eq,pres,sub

# Replicas of this database
#replogfile /var/lib/ldap/openldap-master-replog
#replica host=ldap-1.example.com:389 starttls=critical
#     bindmethod=sasl saslmech=GSSAPI
#     authcId=host/ldap-master.example.com@EXAMPLE.COM
sasl-regexp
   cn=LDAP.Server.Manager
   cn=Manager,dc=acme,dc=com,dc=au

loglevel -1

Listing 3 – default.ldif


dn:		dc=acme,dc=com,dc=au
objectClass:	dcObject
objectClass:	organization
objectClass:	top
o:		acme
dc:		acme

dn:		cn=Manager,dc=acme,dc=com,dc=au
objectclass:	organizationalRole
cn:		Manager

dn: cn=Barbara Jensen,dc=acme,dc=com,dc=au
objectclass: person
cn: Barbara Jensen
cn: Babs Jensen
sn: Jensen
userPassword:	superstr0ngpassw0rd

dn: ou=MAB Segment, dc=acme,dc=com,dc=au
ou: MAB Segment
objectClass: top
objectClass: organizationalUnit
description: MAC Authentication Bypass Sub-Tree

dn: ou=MAC Addresses, ou=MAB Segment, dc=acme,dc=com,dc=au
ou: MAC Addresses
objectClass: top
objectClass: organizationalUnit

dn: ou=MAC Groups, ou=MAB Segment, dc=acme,dc=com,dc=au
ou: MAC Groups
objectClass: top
objectClass: organizationalUnit

dn: cn=acctsprn,ou=MAC Addresses, ou=MAB Segment, dc=acme, dc=com, dc=au
objectClass: top
objectClass: device
objectClass: ieee802Device
macAddress: 00:21:5a:5f:91:c9
cn: acctsprn

dn: cn=printgroup,ou=MAC Groups, ou=MAB Segment, dc=acme, dc=com, dc=au
objectClass: top
objectClass: groupofuniquenames
description: group of delimited MAC Addresses
uniqueMember: cn=acctsprn,ou=MAC Addresses, ou=MAB Segment, dc=acme, dc=com, dc=au
cn: printgroup

Debugging SSL/TLS Certificate Operations with OpenSSL

Filed under: Certificates — Tags: , , , — networknerd @ 9:25 am

OpenSSL provides a convenient method of testing SSL connections to debug problems like untrusted CA certificates and client certificate authentication problems.

The s_client command can be used to debug connections to servers.  In this example I test client certificate authentication to an openldap server.  By using the -msg switch the TLS handshake messages are displayed.  William Stallings wrote an excellent article on the TLS handshake protocol, which I would highly recommend for an easy to understand overview.

[adios@adios-bootcd ~]$ openssl s_client -connect localhost:636 -CAfile /media/usb/ldap/Acme/cacert.pem -cert /media/usb/ldap/Acme/ldapmgr.pem -key /media/usb/ldap/Acme/ldapmgrkey.pem -msg
Enter PEM pass phrase:clientcertpassword
CONNECTED(00000003)
>>> SSL 2.0 [length 008c], CLIENT-HELLO
01 03 01 00 63 00 00 00 20 00 00 39 00 00 38 00
….
9b 73 89 fb de 2e 68 1e 73 da b9 64
<<< TLS 1.0 Handshake [length 004a], ServerHello
02 00 00 46 03 01 49 03 8d fb 96 a9 59 d0 6e 3a
….
51 01 3b 1d 54 5b 66 00 35 00
<<< TLS 1.0 Handshake [length 05cb], Certificate
0b 00 05 c7 00 05 c4 00 02 df 30 82 02 db 30 82
….
ed dc 7c 69 e2 24 d0 04 52 fb 12
depth=1 /C=AU/ST=Queensland/O=Dodgy CA Pty Ltd/CN=Trustmaster
verify return:1
depth=0 /C=AU/ST=Queensland/L=Brisbane/O= Acme Pty Ltd/CN=ldap.acme.com.au/emailAddress=ldapadmin@Acme.com.au
verify return:1
<<< TLS 1.0 Handshake [length 0060], CertificateRequest
0d 00 00 5c 02 01 02 00 57 00 55 30 53 31 0b 30
….
55 04 03 13 0b 54 72 75 73 74 6d 61 73 74 65 72
<<< TLS 1.0 Handshake [length 0004], ServerHelloDone
0e 00 00 00
>>> TLS 1.0 Handshake [length 05cf], Certificate
0b 00 05 cb 00 05 c8 00 02 e3 30 82 02 df 30 82
….
79 95 76 6a ed dc 7c 69 e2 24 d0 04 52 fb 12
>>> TLS 1.0 Handshake [length 0086], ClientKeyExchange
10 00 00 82 00 80 3e 05 96 a4 7c 76 cc 0f 9d 03
….
4e 28 17 81 c2 f8
>>> TLS 1.0 Handshake [length 0086], CertificateVerify
0f 00 00 82 00 80 59 03 45 a1 19 4a ca 4e 02 89
….
5b 67 4c 98 c2 bb
>>> TLS 1.0 ChangeCipherSpec [length 0001]
01
>>> TLS 1.0 Handshake [length 0010], Finished
14 00 00 0c 5b 40 c8 f0 de 25 c3 44 4f c9 79 40
<<< TLS 1.0 ChangeCipherSpec [length 0001]
01
<<< TLS 1.0 Handshake [length 0010], Finished
14 00 00 0c f8 c5 60 53 fb cc a6 67 7f bd 18 ab

Certificate chain
0 s:/C=AU/ST=Queensland/L=Brisbane/O= Acme Pty Ltd/CN=ldap.acme.com.au/emailAddress=ldapadmin@Acme.com.au
i:/C=AU/ST=Queensland/O=Dodgy CA Pty Ltd/CN=Trustmaster
1 s:/C=AU/ST=Queensland/O=Dodgy CA Pty Ltd/CN=Trustmaster
i:/C=AU/ST=Queensland/O=Dodgy CA Pty Ltd/CN=Trustmaster

Server certificate
—–BEGIN CERTIFICATE—–
MIIC2zCCAkSgAwIBAgIJANM+KYmr52JAMA0GCSqGSIb3DQEBBQUAMFMxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIEwpRdWVlbnNsYW5kMRkwFwYDVQQKExBEb2RneSBDQSBQ
dHkgTHRkMRQwEgYDVQQDEwtUcnVzdG1hc3RlcjAeFw0wODEwMTcyMjQxNTZaFw0w
OTEwMTcyMjQxNTZaMIGOMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFu
ZDERMA8GA1UEBxMIQnJpc2JhbmUxFjAUBgNVBAoTDSBBY21lIFB0eSBMdGQxGTAX
BgNVBAMTEGxkYXAuYWNtZS5jb20uYXUxJDAiBgkqhkiG9w0BCQEWFWxkYXBhZG1p
bkBBY21lLmNvbS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAv1643tyt
hwVsNHVu/wdn9MHa9uzdTldbnnZxPbYDyy+IYSHIrhV3E+KGOaUmcfnf5NTuKNRy
XQ0RFgyvkUdF9G6k2LlxDiinXC+8JZ8p1FDBpRjxXaIo66GRKl2KqBvujBOd3Tz7
XGBIvsBQNanrLq5aH7Fo0Mdh270l4zO4xJUCAwEAAaN7MHkwCQYDVR0TBAIwADAs
BglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYD
VR0OBBYEFE+6BZ80WpW1N3+nT80UdrgZSz97MB8GA1UdIwQYMBaAFHP/XSypy1R7
DWslR36JPFtmrmjZMA0GCSqGSIb3DQEBBQUAA4GBABcz3BWYRiAyYh3toM5HQLQN
xXLQFHGz30bYWEqU5vpEOtW1g0VZ2zP5C3bxoIydA4FIrG5Z4Ia1EN/kFy6GPOOE
Dxq3JLOc6oCZNykWf4zu957rG1YSdOvxXrjZ3+FTpz8gyULj9OT9ILJ8inLHioq7
G4oI5wR4HmSPcC945Lo/
—–END CERTIFICATE—–
subject=/C=AU/ST=Queensland/L=Brisbane/O= Acme Pty Ltd/CN=ldap.acme.com.au/emailAddress=ldapadmin@Acme.com.au
issuer=/C=AU/ST=Queensland/O=Dodgy CA Pty Ltd/CN=Trustmaster

Acceptable client certificate CA names
/C=AU/ST=Queensland/O=Dodgy CA Pty Ltd/CN=Trustmaster

SSL handshake has read 1731 bytes and written 1971 bytes

New, TLSv1/SSLv3, Cipher is AES256-SHA
Server public key is 1024 bit
SSL-Session:
Protocol  : TLSv1
Cipher    : AES256-SHA
Session-ID: 3EB070B9ACEFE43151F93E17496D779ABE8A50FE463CE73F0851013B1D545B66
Session-ID-ctx:
Master-Key: 669A8E689E26D4A4B738E2FC2CCC01E99DF571463DD8E6668339C5E72C761209134F83B1C57CE8B9161191B9AF7E97ED
Key-Arg   : None
Krb5 Principal: None
Start Time: 1224969723
Timeout   : 300 (sec)
Verify return code: 0 (ok)

Since the ldap server requires a client certificate if we fail to provide one we will get a fatal handshake failure

[root@adios-bootcd ~]# openssl s_client -connect localhost:636 -CAfile /media/usb/ldap/Acme/cacert.pem  -msg
CONNECTED(00000003)
>>> SSL 2.0 [length 008c], CLIENT-HELLO
01 03 01 00 63 00 00 00 20 00 00 39 00 00 38 00
….
e9 c4 3b 49 97 30 e8 27 f8 51 bd c6
<<< TLS 1.0 Handshake [length 004a], ServerHello
02 00 00 46 03 01 49 03 a0 14 ec 91 6e ef d1 c5
….
34 d1 11 63 12 5a 88 00 35 00
<<< TLS 1.0 Handshake [length 05cb], Certificate
0b 00 05 c7 00 05 c4 00 02 df 30 82 02 db 30 82
….
ed dc 7c 69 e2 24 d0 04 52 fb 12
depth=1 /C=AU/ST=Queensland/O=Dodgy CA Pty Ltd/CN=Trustmaster
verify return:1
depth=0 /C=AU/ST=Queensland/L=Brisbane/O= Acme Pty Ltd/CN=ldap.acme.com.au/emailAddress=ldapadmin@Acme.com.au
verify return:1
<<< TLS 1.0 Handshake [length 0060], CertificateRequest
0d 00 00 5c 02 01 02 00 57 00 55 30 53 31 0b 30
….
55 04 03 13 0b 54 72 75 73 74 6d 61 73 74 65 72
<<< TLS 1.0 Handshake [length 0004], ServerHelloDone
0e 00 00 00
>>> TLS 1.0 Handshake [length 0007], Certificate
0b 00 00 03 00 00 00
>>> TLS 1.0 Handshake [length 0086], ClientKeyExchange
10 00 00 82 00 80 5c 31 33 b3 37 a5 e2 aa 6a 05
….
64 fe fa 8d aa 21
>>> TLS 1.0 ChangeCipherSpec [length 0001]
01
>>> TLS 1.0 Handshake [length 0010], Finished
14 00 00 0c f2 19 92 71 f2 8d c0 84 00 3a 0a 7b
<<< TLS 1.0 Alert [length 0002], fatal handshake_failure
02 28
4607:error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:s3_pkt.c:1052:SSL alert number 40
4607:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake failure:s23_lib.c:226:

Similarly if the CA certificate of the server is untrusted we will get errors but OpenSSL will continue with the connection, as can be seen in the output of the verify routine in response to the server certificate message.

[adios@adios-bootcd ~]$ openssl s_client -connect localhost:636   -msg
CONNECTED(00000003)
>>> SSL 2.0 [length 008c], CLIENT-HELLO
01 03 01 00 63 00 00 00 20 00 00 39 00 00 38 00
….
d2 4d 34 75 dc 75 57 b8 d9 9a 52 3a
<<< TLS 1.0 Handshake [length 004a], ServerHello
02 00 00 46 03 01 49 03 a8 82 ca 0d 54 68 ee f7
….
60 ed bb 9d 4a ba 7f 00 35 00
<<< TLS 1.0 Handshake [length 05cb], Certificate
0b 00 05 c7 00 05 c4 00 02 df 30 82 02 db 30 82
….
ed dc 7c 69 e2 24 d0 04 52 fb 12
depth=1 /C=AU/ST=Queensland/O=Dodgy CA Pty Ltd/CN=Trustmaster
verify error:num=19:self signed certificate in certificate chain
verify return:0
<<< TLS 1.0 Handshake [length 0004], ServerHelloDone
0e 00 00 00
>>> TLS 1.0 Handshake [length 0086], ClientKeyExchange
10 00 00 82 00 80 2e 4d f8 4a 1f 70 be 25 00 d9
….
0f d7 2a c8 cd f0
>>> TLS 1.0 ChangeCipherSpec [length 0001]
01
>>> TLS 1.0 Handshake [length 0010], Finished
14 00 00 0c db 63 b6 e9 03 bf 3a 9a 17 ac 70 06
<<< TLS 1.0 ChangeCipherSpec [length 0001]
01
<<< TLS 1.0 Handshake [length 0010], Finished
14 00 00 0c 8d 56 fd 05 01 dc a1 1e 64 8b fc cd

Certificate chain
0 s:/C=AU/ST=Queensland/L=Brisbane/O= Acme Pty Ltd/CN=ldap.acme.com.au/emailAddress=ldapadmin@Acme.com.au
i:/C=AU/ST=Queensland/O=Dodgy CA Pty Ltd/CN=Trustmaster
1 s:/C=AU/ST=Queensland/O=Dodgy CA Pty Ltd/CN=Trustmaster
i:/C=AU/ST=Queensland/O=Dodgy CA Pty Ltd/CN=Trustmaster

Server certificate
—–BEGIN CERTIFICATE—–
MIIC2zCCAkSgAwIBAgIJANM+KYmr52JAMA0GCSqGSIb3DQEBBQUAMFMxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIEwpRdWVlbnNsYW5kMRkwFwYDVQQKExBEb2RneSBDQSBQ
dHkgTHRkMRQwEgYDVQQDEwtUcnVzdG1hc3RlcjAeFw0wODEwMTcyMjQxNTZaFw0w
OTEwMTcyMjQxNTZaMIGOMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFu
ZDERMA8GA1UEBxMIQnJpc2JhbmUxFjAUBgNVBAoTDSBBY21lIFB0eSBMdGQxGTAX
BgNVBAMTEGxkYXAuYWNtZS5jb20uYXUxJDAiBgkqhkiG9w0BCQEWFWxkYXBhZG1p
bkBBY21lLmNvbS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAv1643tyt
hwVsNHVu/wdn9MHa9uzdTldbnnZxPbYDyy+IYSHIrhV3E+KGOaUmcfnf5NTuKNRy
XQ0RFgyvkUdF9G6k2LlxDiinXC+8JZ8p1FDBpRjxXaIo66GRKl2KqBvujBOd3Tz7
XGBIvsBQNanrLq5aH7Fo0Mdh270l4zO4xJUCAwEAAaN7MHkwCQYDVR0TBAIwADAs
BglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYD
VR0OBBYEFE+6BZ80WpW1N3+nT80UdrgZSz97MB8GA1UdIwQYMBaAFHP/XSypy1R7
DWslR36JPFtmrmjZMA0GCSqGSIb3DQEBBQUAA4GBABcz3BWYRiAyYh3toM5HQLQN
xXLQFHGz30bYWEqU5vpEOtW1g0VZ2zP5C3bxoIydA4FIrG5Z4Ia1EN/kFy6GPOOE
Dxq3JLOc6oCZNykWf4zu957rG1YSdOvxXrjZ3+FTpz8gyULj9OT9ILJ8inLHioq7
G4oI5wR4HmSPcC945Lo/
—–END CERTIFICATE—–
subject=/C=AU/ST=Queensland/L=Brisbane/O= Acme Pty Ltd/CN=ldap.acme.com.au/emailAddress=ldapadmin@Acme.com.au
issuer=/C=AU/ST=Queensland/O=Dodgy CA Pty Ltd/CN=Trustmaster

No client certificate CA names sent

SSL handshake has read 1635 bytes and written 340 bytes

New, TLSv1/SSLv3, Cipher is AES256-SHA
Server public key is 1024 bit
SSL-Session:
Protocol  : TLSv1
Cipher    : AES256-SHA
Session-ID: 577521F8CAD8508B6C9B66EDAADBD2B63D481A16A87B77982D60EDBB9D4ABA7F
Session-ID-ctx:
Master-Key: 53521EACA3173067D467E53EABB67869A8E17489DF201972F29314DC3BC4103AE80194F5EAB768F929CFD98B5EDEFC30
Key-Arg   : None
Krb5 Principal: None
Start Time: 1224976514
Timeout   : 300 (sec)
Verify return code: 19 (self signed certificate in certificate chain)

« Newer PostsOlder Posts »

Blog at WordPress.com.