Skip to content

Instantly share code, notes, and snippets.

@pudquick
Last active March 26, 2017 00:35
Show Gist options
  • Save pudquick/ae066b62593924bdcc3ca0baf17a5689 to your computer and use it in GitHub Desktop.
Save pudquick/ae066b62593924bdcc3ca0baf17a5689 to your computer and use it in GitHub Desktop.
This is a quick-n-dirty implementation of decoding the LDAP Ping netlogon response in Swift
import Foundation
//-------------------------------------------------------
// this is just setup / test environment stuff
// we would normally have the output from ldapsearch here
//-------------------------------------------------------
let fakeout = "netlogon: FwAA...\n" +
" lYXMw...........\n" +
" bGFy......="
// preserve just the value, not the attribute name
var nl_value = fakeout.componentsSeparatedByString(": ")[1]
// Remove newlines and spaces
let whitespace = NSCharacterSet.whitespaceAndNewlineCharacterSet()
nl_value = nl_value.stringByReplacingOccurrencesOfString(" ", withString: "")
nl_value = nl_value.stringByReplacingOccurrencesOfString("\n", withString: "")
// Now we have it as data bytes
var nl_data: NSData = NSData(base64EncodedString: nl_value, options: [])!
//------------------------------------------------------------------------
// this is the end of setup, assume we have "nl_data" as NSData containing
// the real data that we want to work on and all the rest will be fine
//------------------------------------------------------------------------
enum DecodeError: ErrorType {
case IllegalTag
case CyclicPointer
}
func d_rfc1035(buffer: NSData, start: UInt16, seen: Set<UInt16>?) throws -> (r: String, c: UInt16) {
let marker: UInt8 = 0xc0
var cursor: UInt16 = start
var result: [String] = []
var pointers: Set<UInt16> = Set<UInt16>()
if (seen != nil) {
pointers.unionInPlace(seen!)
}
while true {
var tag: UInt8 = 0
buffer.getBytes(&tag, range: NSRange(location: Int(cursor), length: 1))
cursor += 1
if (tag == 0) {
// end of a sequence, time to tally up and return results
break
} else if ((tag & marker) == marker) {
var byte: UInt8 = 0
buffer.getBytes(&byte, range: NSRange(location: Int(cursor), length: 1))
cursor += 1
// we would appear to have a pointer, let's remember it
var ptr: UInt16 = 0
let d: [UInt8] = [byte, (tag & ~marker)]
ptr += UnsafePointer<UInt16>(d).memory
// check if we've seen it before already
if pointers.contains(ptr) {
throw DecodeError.CyclicPointer
}
pointers.insert(ptr)
let (sresult, _) = try d_rfc1035(buffer, start: ptr, seen: pointers)
result.append(sresult)
break
} else if ((tag & marker) > 0) {
throw DecodeError.IllegalTag
} else {
// read 'tag'-many bytes
var s: [UInt8] = [UInt8](count: Int(tag), repeatedValue: 0)
buffer.getBytes(&s, range: NSRange(location: Int(cursor), length: Int(tag)))
cursor += UInt16(tag)
result.append(NSString(bytes: s, length: Int(tag), encoding: NSUTF8StringEncoding)! as String)
}
}
let final = result.joinWithSeparator(".")
return (final, cursor)
}
// type
var nl_type: UInt32 = 0
nl_data.getBytes(&nl_type, range: NSRange(location: 0, length: 4))
// flags
var nl_flags: UInt32 = 0
nl_data.getBytes(&nl_flags, range: NSRange(location: 4, length: 4))
// domain guid
var uuid_bytes: [UInt8] = [UInt8](count: 16, repeatedValue: 0)
nl_data.getBytes(&uuid_bytes, range: NSRange(location: 8, length: 16))
var nl_domain_guid: NSUUID = NSUUID(UUIDBytes: uuid_bytes)
// begin parsing the rfc1035 encoded buffer
let c_forest = UInt16(24)
// forest, domain, hostname, netbios_domain,
// netbios_hostname, user, client_site, server_site
let (forest, c_domain) = try d_rfc1035(nl_data, start: c_forest, seen: nil)
let (domain, c_hostname) = try d_rfc1035(nl_data, start: c_domain, seen: nil)
let (hostname, c_nbdomain) = try d_rfc1035(nl_data, start: c_hostname, seen: nil)
let (netbios_domain, c_nbhostname) = try d_rfc1035(nl_data, start: c_nbdomain, seen: nil)
let (netbios_hostname, c_user) = try d_rfc1035(nl_data, start: c_nbhostname, seen: nil)
let (user, c_csite) = try d_rfc1035(nl_data, start: c_user, seen: nil)
let (client_site, c_ssite) = try d_rfc1035(nl_data, start: c_csite, seen: nil)
let (server_site, _) = try d_rfc1035(nl_data, start: c_ssite, seen: nil)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment