Last active
March 26, 2017 00:35
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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