Add xormask option
This commit is contained in:
parent
642a6763d1
commit
e69079d1f6
|
@ -3,7 +3,7 @@
|
||||||
// TunnelKit
|
// TunnelKit
|
||||||
//
|
//
|
||||||
// Created by Davide De Rosa on 5/23/19.
|
// Created by Davide De Rosa on 5/23/19.
|
||||||
// Copyright (c) 2021 Davide De Rosa. All rights reserved.
|
// Copyright (c) 2021 Davide De Rosa, Sam Foxman. All rights reserved.
|
||||||
//
|
//
|
||||||
// https://github.com/passepartoutvpn
|
// https://github.com/passepartoutvpn
|
||||||
//
|
//
|
||||||
|
@ -30,6 +30,8 @@ public protocol LinkProducer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns a `LinkInterface`.
|
Returns a `LinkInterface`.
|
||||||
|
|
||||||
|
- Parameter xorMask: The XOR mask.
|
||||||
**/
|
**/
|
||||||
func link() -> LinkInterface
|
func link(xorMask: UInt8?) -> LinkInterface
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// TunnelKit
|
// TunnelKit
|
||||||
//
|
//
|
||||||
// Created by Davide De Rosa on 8/27/17.
|
// Created by Davide De Rosa on 8/27/17.
|
||||||
// Copyright (c) 2021 Davide De Rosa. All rights reserved.
|
// Copyright (c) 2021 Davide De Rosa, Sam Foxman. All rights reserved.
|
||||||
//
|
//
|
||||||
// https://github.com/passepartoutvpn
|
// https://github.com/passepartoutvpn
|
||||||
//
|
//
|
||||||
|
@ -47,4 +47,7 @@ public protocol LinkInterface: IOInterface {
|
||||||
|
|
||||||
/// The number of packets that this interface is able to bufferize.
|
/// The number of packets that this interface is able to bufferize.
|
||||||
var packetBufferSize: Int { get }
|
var packetBufferSize: Int { get }
|
||||||
|
|
||||||
|
/// A byte to xor all packet payloads with.
|
||||||
|
var xorMask: UInt8 { get }
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// TunnelKit
|
// TunnelKit
|
||||||
//
|
//
|
||||||
// Created by Davide De Rosa on 5/23/19.
|
// Created by Davide De Rosa on 5/23/19.
|
||||||
// Copyright (c) 2021 Davide De Rosa. All rights reserved.
|
// Copyright (c) 2021 Davide De Rosa, Sam Foxman. All rights reserved.
|
||||||
//
|
//
|
||||||
// https://github.com/passepartoutvpn
|
// https://github.com/passepartoutvpn
|
||||||
//
|
//
|
||||||
|
@ -32,9 +32,12 @@ class NETCPLink: LinkInterface {
|
||||||
|
|
||||||
private let maxPacketSize: Int
|
private let maxPacketSize: Int
|
||||||
|
|
||||||
init(impl: NWTCPConnection, maxPacketSize: Int? = nil) {
|
let xorMask: UInt8
|
||||||
|
|
||||||
|
init(impl: NWTCPConnection, maxPacketSize: Int? = nil, xorMask: UInt8?) {
|
||||||
self.impl = impl
|
self.impl = impl
|
||||||
self.maxPacketSize = maxPacketSize ?? (512 * 1024)
|
self.maxPacketSize = maxPacketSize ?? (512 * 1024)
|
||||||
|
self.xorMask = xorMask ?? 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: LinkInterface
|
// MARK: LinkInterface
|
||||||
|
@ -57,7 +60,7 @@ class NETCPLink: LinkInterface {
|
||||||
|
|
||||||
// WARNING: runs in Network.framework queue
|
// WARNING: runs in Network.framework queue
|
||||||
impl.readMinimumLength(2, maximumLength: packetBufferSize) { [weak self] (data, error) in
|
impl.readMinimumLength(2, maximumLength: packetBufferSize) { [weak self] (data, error) in
|
||||||
guard let _ = self else {
|
guard let self = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
queue.sync {
|
queue.sync {
|
||||||
|
@ -69,9 +72,9 @@ class NETCPLink: LinkInterface {
|
||||||
var newBuffer = buffer
|
var newBuffer = buffer
|
||||||
newBuffer.append(contentsOf: data)
|
newBuffer.append(contentsOf: data)
|
||||||
var until = 0
|
var until = 0
|
||||||
let packets = PacketStream.packets(fromStream: newBuffer, until: &until)
|
let packets = PacketStream.packets(fromStream: newBuffer, until: &until, xorMask: self.xorMask)
|
||||||
newBuffer = newBuffer.subdata(in: until..<newBuffer.count)
|
newBuffer = newBuffer.subdata(in: until..<newBuffer.count)
|
||||||
self?.loopReadPackets(queue, newBuffer, handler)
|
self.loopReadPackets(queue, newBuffer, handler)
|
||||||
|
|
||||||
handler(packets, nil)
|
handler(packets, nil)
|
||||||
}
|
}
|
||||||
|
@ -79,14 +82,14 @@ class NETCPLink: LinkInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
func writePacket(_ packet: Data, completionHandler: ((Error?) -> Void)?) {
|
func writePacket(_ packet: Data, completionHandler: ((Error?) -> Void)?) {
|
||||||
let stream = PacketStream.stream(fromPacket: packet)
|
let stream = PacketStream.stream(fromPacket: packet, xorMask: xorMask)
|
||||||
impl.write(stream) { (error) in
|
impl.write(stream) { (error) in
|
||||||
completionHandler?(error)
|
completionHandler?(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func writePackets(_ packets: [Data], completionHandler: ((Error?) -> Void)?) {
|
func writePackets(_ packets: [Data], completionHandler: ((Error?) -> Void)?) {
|
||||||
let stream = PacketStream.stream(fromPackets: packets)
|
let stream = PacketStream.stream(fromPackets: packets, xorMask: xorMask)
|
||||||
impl.write(stream) { (error) in
|
impl.write(stream) { (error) in
|
||||||
completionHandler?(error)
|
completionHandler?(error)
|
||||||
}
|
}
|
||||||
|
@ -95,7 +98,7 @@ class NETCPLink: LinkInterface {
|
||||||
|
|
||||||
/// :nodoc:
|
/// :nodoc:
|
||||||
extension NETCPSocket: LinkProducer {
|
extension NETCPSocket: LinkProducer {
|
||||||
public func link() -> LinkInterface {
|
public func link(xorMask: UInt8?) -> LinkInterface {
|
||||||
return NETCPLink(impl: impl)
|
return NETCPLink(impl: impl, maxPacketSize: nil, xorMask: xorMask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// TunnelKit
|
// TunnelKit
|
||||||
//
|
//
|
||||||
// Created by Davide De Rosa on 5/23/19.
|
// Created by Davide De Rosa on 5/23/19.
|
||||||
// Copyright (c) 2021 Davide De Rosa. All rights reserved.
|
// Copyright (c) 2021 Davide De Rosa, Sam Foxman. All rights reserved.
|
||||||
//
|
//
|
||||||
// https://github.com/passepartoutvpn
|
// https://github.com/passepartoutvpn
|
||||||
//
|
//
|
||||||
|
@ -31,9 +31,12 @@ class NEUDPLink: LinkInterface {
|
||||||
|
|
||||||
private let maxDatagrams: Int
|
private let maxDatagrams: Int
|
||||||
|
|
||||||
init(impl: NWUDPSession, maxDatagrams: Int? = nil) {
|
let xorMask: UInt8
|
||||||
|
|
||||||
|
init(impl: NWUDPSession, maxDatagrams: Int? = nil, xorMask: UInt8?) {
|
||||||
self.impl = impl
|
self.impl = impl
|
||||||
self.maxDatagrams = maxDatagrams ?? 200
|
self.maxDatagrams = maxDatagrams ?? 200
|
||||||
|
self.xorMask = xorMask ?? 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: LinkInterface
|
// MARK: LinkInterface
|
||||||
|
@ -51,24 +54,46 @@ class NEUDPLink: LinkInterface {
|
||||||
func setReadHandler(queue: DispatchQueue, _ handler: @escaping ([Data]?, Error?) -> Void) {
|
func setReadHandler(queue: DispatchQueue, _ handler: @escaping ([Data]?, Error?) -> Void) {
|
||||||
|
|
||||||
// WARNING: runs in Network.framework queue
|
// WARNING: runs in Network.framework queue
|
||||||
impl.setReadHandler({ [weak self] (packets, error) in
|
impl.setReadHandler({ [weak self] packets, error in
|
||||||
guard let _ = self else {
|
guard let self = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
queue.sync {
|
var packetsToUse: [Data]?
|
||||||
handler(packets, error)
|
if let packets = packets, self.xorMask != 0 {
|
||||||
|
packetsToUse = packets.map { packet in
|
||||||
|
Data(bytes: packet.map { $0 ^ self.xorMask }, count: packet.count)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
packetsToUse = packets
|
||||||
}
|
}
|
||||||
}, maxDatagrams: maxDatagrams)
|
queue.sync {
|
||||||
|
handler(packetsToUse, error)
|
||||||
|
}
|
||||||
|
}, maxDatagrams: maxDatagrams)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writePacket(_ packet: Data, completionHandler: ((Error?) -> Void)?) {
|
func writePacket(_ packet: Data, completionHandler: ((Error?) -> Void)?) {
|
||||||
impl.writeDatagram(packet) { (error) in
|
var dataToUse: Data
|
||||||
|
if xorMask != 0 {
|
||||||
|
dataToUse = Data(bytes: packet.map { $0 ^ xorMask }, count: packet.count)
|
||||||
|
} else {
|
||||||
|
dataToUse = packet
|
||||||
|
}
|
||||||
|
impl.writeDatagram(dataToUse) { error in
|
||||||
completionHandler?(error)
|
completionHandler?(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func writePackets(_ packets: [Data], completionHandler: ((Error?) -> Void)?) {
|
func writePackets(_ packets: [Data], completionHandler: ((Error?) -> Void)?) {
|
||||||
impl.writeMultipleDatagrams(packets) { (error) in
|
var packetsToUse: [Data]
|
||||||
|
if xorMask != 0 {
|
||||||
|
packetsToUse = packets.map { packet in
|
||||||
|
Data(bytes: packet.map { $0 ^ xorMask }, count: packet.count)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
packetsToUse = packets
|
||||||
|
}
|
||||||
|
impl.writeMultipleDatagrams(packetsToUse) { error in
|
||||||
completionHandler?(error)
|
completionHandler?(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,7 +101,7 @@ class NEUDPLink: LinkInterface {
|
||||||
|
|
||||||
/// :nodoc:
|
/// :nodoc:
|
||||||
extension NEUDPSocket: LinkProducer {
|
extension NEUDPSocket: LinkProducer {
|
||||||
public func link() -> LinkInterface {
|
public func link(xorMask: UInt8?) -> LinkInterface {
|
||||||
return NEUDPLink(impl: impl)
|
return NEUDPLink(impl: impl, maxDatagrams: nil, xorMask: xorMask)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// TunnelKit
|
// TunnelKit
|
||||||
//
|
//
|
||||||
// Created by Davide De Rosa on 10/23/17.
|
// Created by Davide De Rosa on 10/23/17.
|
||||||
// Copyright (c) 2021 Davide De Rosa. All rights reserved.
|
// Copyright (c) 2021 Davide De Rosa, Sam Foxman. All rights reserved.
|
||||||
//
|
//
|
||||||
// https://github.com/passepartoutvpn
|
// https://github.com/passepartoutvpn
|
||||||
//
|
//
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// TunnelKit
|
// TunnelKit
|
||||||
//
|
//
|
||||||
// Created by Davide De Rosa on 2/1/17.
|
// Created by Davide De Rosa on 2/1/17.
|
||||||
// Copyright (c) 2021 Davide De Rosa. All rights reserved.
|
// Copyright (c) 2021 Davide De Rosa, Sam Foxman. All rights reserved.
|
||||||
//
|
//
|
||||||
// https://github.com/passepartoutvpn
|
// https://github.com/passepartoutvpn
|
||||||
//
|
//
|
||||||
|
@ -454,10 +454,10 @@ extension OpenVPNTunnelProvider: GenericSocketDelegate {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if session.canRebindLink() {
|
if session.canRebindLink() {
|
||||||
session.rebindLink(producer.link())
|
session.rebindLink(producer.link(xorMask: cfg.sessionConfiguration.xorMask))
|
||||||
reasserting = false
|
reasserting = false
|
||||||
} else {
|
} else {
|
||||||
session.setLink(producer.link())
|
session.setLink(producer.link(xorMask: cfg.sessionConfiguration.xorMask))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// TunnelKit
|
// TunnelKit
|
||||||
//
|
//
|
||||||
// Created by Davide De Rosa on 8/23/18.
|
// Created by Davide De Rosa on 8/23/18.
|
||||||
// Copyright (c) 2021 Davide De Rosa. All rights reserved.
|
// Copyright (c) 2021 Davide De Rosa, Sam Foxman. All rights reserved.
|
||||||
//
|
//
|
||||||
// https://github.com/passepartoutvpn
|
// https://github.com/passepartoutvpn
|
||||||
//
|
//
|
||||||
|
@ -216,6 +216,9 @@ extension OpenVPN {
|
||||||
/// The number of seconds after which a renegotiation should be initiated. If `nil`, the client will never initiate a renegotiation.
|
/// The number of seconds after which a renegotiation should be initiated. If `nil`, the client will never initiate a renegotiation.
|
||||||
public var renegotiatesAfter: TimeInterval?
|
public var renegotiatesAfter: TimeInterval?
|
||||||
|
|
||||||
|
/// A byte to xor all packet payloads with.
|
||||||
|
public var xorMask: UInt8?
|
||||||
|
|
||||||
// MARK: Client
|
// MARK: Client
|
||||||
|
|
||||||
/// The server hostname (picked from first remote).
|
/// The server hostname (picked from first remote).
|
||||||
|
@ -324,6 +327,7 @@ extension OpenVPN {
|
||||||
keepAliveInterval: keepAliveInterval,
|
keepAliveInterval: keepAliveInterval,
|
||||||
keepAliveTimeout: keepAliveTimeout,
|
keepAliveTimeout: keepAliveTimeout,
|
||||||
renegotiatesAfter: renegotiatesAfter,
|
renegotiatesAfter: renegotiatesAfter,
|
||||||
|
xorMask: xorMask,
|
||||||
hostname: hostname,
|
hostname: hostname,
|
||||||
endpointProtocols: endpointProtocols,
|
endpointProtocols: endpointProtocols,
|
||||||
checksEKU: checksEKU,
|
checksEKU: checksEKU,
|
||||||
|
@ -414,6 +418,9 @@ extension OpenVPN {
|
||||||
/// - Seealso: `ConfigurationBuilder.renegotiatesAfter`
|
/// - Seealso: `ConfigurationBuilder.renegotiatesAfter`
|
||||||
public let renegotiatesAfter: TimeInterval?
|
public let renegotiatesAfter: TimeInterval?
|
||||||
|
|
||||||
|
/// - Seealso: `ConfigurationBuilder.xorMask`
|
||||||
|
public let xorMask: UInt8?
|
||||||
|
|
||||||
/// - Seealso: `ConfigurationBuilder.hostname`
|
/// - Seealso: `ConfigurationBuilder.hostname`
|
||||||
public let hostname: String?
|
public let hostname: String?
|
||||||
|
|
||||||
|
@ -545,6 +552,7 @@ extension OpenVPN.Configuration {
|
||||||
builder.proxyAutoConfigurationURL = proxyAutoConfigurationURL
|
builder.proxyAutoConfigurationURL = proxyAutoConfigurationURL
|
||||||
builder.proxyBypassDomains = proxyBypassDomains
|
builder.proxyBypassDomains = proxyBypassDomains
|
||||||
builder.routingPolicies = routingPolicies
|
builder.routingPolicies = routingPolicies
|
||||||
|
builder.xorMask = xorMask
|
||||||
return builder
|
return builder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// TunnelKit
|
// TunnelKit
|
||||||
//
|
//
|
||||||
// Created by Davide De Rosa on 9/5/18.
|
// Created by Davide De Rosa on 9/5/18.
|
||||||
// Copyright (c) 2021 Davide De Rosa. All rights reserved.
|
// Copyright (c) 2021 Davide De Rosa, Sam Foxman. All rights reserved.
|
||||||
//
|
//
|
||||||
// https://github.com/passepartoutvpn
|
// https://github.com/passepartoutvpn
|
||||||
//
|
//
|
||||||
|
@ -60,6 +60,8 @@ extension OpenVPN {
|
||||||
|
|
||||||
static let renegSec = NSRegularExpression("^reneg-sec +\\d+")
|
static let renegSec = NSRegularExpression("^reneg-sec +\\d+")
|
||||||
|
|
||||||
|
static let xorMask = NSRegularExpression("^scramble +xormask +.$")
|
||||||
|
|
||||||
static let blockBegin = NSRegularExpression("^<[\\w\\-]+>")
|
static let blockBegin = NSRegularExpression("^<[\\w\\-]+>")
|
||||||
|
|
||||||
static let blockEnd = NSRegularExpression("^<\\/[\\w\\-]+>")
|
static let blockEnd = NSRegularExpression("^<\\/[\\w\\-]+>")
|
||||||
|
@ -218,6 +220,7 @@ extension OpenVPN {
|
||||||
var optKeepAliveSeconds: TimeInterval?
|
var optKeepAliveSeconds: TimeInterval?
|
||||||
var optKeepAliveTimeoutSeconds: TimeInterval?
|
var optKeepAliveTimeoutSeconds: TimeInterval?
|
||||||
var optRenegotiateAfterSeconds: TimeInterval?
|
var optRenegotiateAfterSeconds: TimeInterval?
|
||||||
|
var optXorMask: UInt8?
|
||||||
//
|
//
|
||||||
var optDefaultProto: SocketType?
|
var optDefaultProto: SocketType?
|
||||||
var optDefaultPort: UInt16?
|
var optDefaultPort: UInt16?
|
||||||
|
@ -459,6 +462,13 @@ extension OpenVPN {
|
||||||
}
|
}
|
||||||
optRenegotiateAfterSeconds = TimeInterval(arg)
|
optRenegotiateAfterSeconds = TimeInterval(arg)
|
||||||
}
|
}
|
||||||
|
Regex.xorMask.enumerateArguments(in: line) {
|
||||||
|
isHandled = true
|
||||||
|
if $0.count != 2 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
optXorMask = Character($0[1]).asciiValue
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: Client
|
// MARK: Client
|
||||||
|
|
||||||
|
@ -726,6 +736,7 @@ extension OpenVPN {
|
||||||
sessionBuilder.checksEKU = optChecksEKU
|
sessionBuilder.checksEKU = optChecksEKU
|
||||||
sessionBuilder.randomizeEndpoint = optRandomizeEndpoint
|
sessionBuilder.randomizeEndpoint = optRandomizeEndpoint
|
||||||
sessionBuilder.mtu = optMTU
|
sessionBuilder.mtu = optMTU
|
||||||
|
sessionBuilder.xorMask = optXorMask
|
||||||
|
|
||||||
// MARK: Server
|
// MARK: Server
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// TunnelKit
|
// TunnelKit
|
||||||
//
|
//
|
||||||
// Created by Davide De Rosa on 4/25/19.
|
// Created by Davide De Rosa on 4/25/19.
|
||||||
// Copyright (c) 2021 Davide De Rosa. All rights reserved.
|
// Copyright (c) 2021 Davide De Rosa, Sam Foxman. All rights reserved.
|
||||||
//
|
//
|
||||||
// https://github.com/passepartoutvpn
|
// https://github.com/passepartoutvpn
|
||||||
//
|
//
|
||||||
|
@ -29,9 +29,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@interface PacketStream : NSObject
|
@interface PacketStream : NSObject
|
||||||
|
|
||||||
+ (NSArray<NSData *> *)packetsFromStream:(NSData *)stream until:(nullable NSInteger *)until;
|
+ (NSArray<NSData *> *)packetsFromStream:(NSData *)stream until:(NSInteger *)until xorMask:(uint8_t)xorMask;
|
||||||
+ (NSData *)streamFromPacket:(NSData *)packet;
|
+ (NSData *)streamFromPacket:(NSData *)packet xorMask:(uint8_t)xorMask;
|
||||||
+ (NSData *)streamFromPackets:(NSArray<NSData *> *)packets;
|
+ (NSData *)streamFromPackets:(NSArray<NSData *> *)packets xorMask:(uint8_t)xorMask;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// TunnelKit
|
// TunnelKit
|
||||||
//
|
//
|
||||||
// Created by Davide De Rosa on 4/25/19.
|
// Created by Davide De Rosa on 4/25/19.
|
||||||
// Copyright (c) 2021 Davide De Rosa. All rights reserved.
|
// Copyright (c) 2021 Davide De Rosa, Sam Foxman. All rights reserved.
|
||||||
//
|
//
|
||||||
// https://github.com/passepartoutvpn
|
// https://github.com/passepartoutvpn
|
||||||
//
|
//
|
||||||
|
@ -29,7 +29,18 @@ static const NSInteger PacketStreamHeaderLength = sizeof(uint16_t);
|
||||||
|
|
||||||
@implementation PacketStream
|
@implementation PacketStream
|
||||||
|
|
||||||
+ (NSArray<NSData *> *)packetsFromStream:(NSData *)stream until:(NSInteger *)until
|
+ (void)memcpyXor:(uint8_t *)dst src:(NSData *)src xorMask:(uint8_t)xorMask
|
||||||
|
{
|
||||||
|
if (xorMask != 0) {
|
||||||
|
for (int i = 0; i < src.length; ++i) {
|
||||||
|
dst[i] = ((uint8_t *)(src.bytes))[i] ^ xorMask;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy(dst, src.bytes, src.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSArray<NSData *> *)packetsFromStream:(NSData *)stream until:(NSInteger *)until xorMask:(uint8_t)xorMask
|
||||||
{
|
{
|
||||||
NSInteger ni = 0;
|
NSInteger ni = 0;
|
||||||
NSMutableArray<NSData *> *parsed = [[NSMutableArray alloc] init];
|
NSMutableArray<NSData *> *parsed = [[NSMutableArray alloc] init];
|
||||||
|
@ -42,6 +53,12 @@ static const NSInteger PacketStreamHeaderLength = sizeof(uint16_t);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
NSData *packet = [stream subdataWithRange:NSMakeRange(start, packlen)];
|
NSData *packet = [stream subdataWithRange:NSMakeRange(start, packlen)];
|
||||||
|
uint8_t* packetBytes = (uint8_t*) packet.bytes;
|
||||||
|
if (xorMask != 0) {
|
||||||
|
for (int i = 0; i < packet.length; i++) {
|
||||||
|
packetBytes[i] ^= xorMask;
|
||||||
|
}
|
||||||
|
}
|
||||||
[parsed addObject:packet];
|
[parsed addObject:packet];
|
||||||
ni = end;
|
ni = end;
|
||||||
}
|
}
|
||||||
|
@ -51,19 +68,19 @@ static const NSInteger PacketStreamHeaderLength = sizeof(uint16_t);
|
||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSData *)streamFromPacket:(NSData *)packet
|
+ (NSData *)streamFromPacket:(NSData *)packet xorMask:(uint8_t)xorMask
|
||||||
{
|
{
|
||||||
NSMutableData *raw = [[NSMutableData alloc] initWithLength:(PacketStreamHeaderLength + packet.length)];
|
NSMutableData *raw = [[NSMutableData alloc] initWithLength:(PacketStreamHeaderLength + packet.length)];
|
||||||
|
|
||||||
uint8_t *ptr = raw.mutableBytes;
|
uint8_t *ptr = raw.mutableBytes;
|
||||||
*(uint16_t *)ptr = CFSwapInt16HostToBig(packet.length);
|
*(uint16_t *)ptr = CFSwapInt16HostToBig(packet.length);
|
||||||
ptr += PacketStreamHeaderLength;
|
ptr += PacketStreamHeaderLength;
|
||||||
memcpy(ptr, packet.bytes, packet.length);
|
[PacketStream memcpyXor:ptr src:packet xorMask:xorMask];
|
||||||
|
|
||||||
return raw;
|
return raw;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSData *)streamFromPackets:(NSArray<NSData *> *)packets;
|
+ (NSData *)streamFromPackets:(NSArray<NSData *> *)packets xorMask:(uint8_t)xorMask
|
||||||
{
|
{
|
||||||
NSInteger streamLength = 0;
|
NSInteger streamLength = 0;
|
||||||
for (NSData *p in packets) {
|
for (NSData *p in packets) {
|
||||||
|
@ -75,7 +92,7 @@ static const NSInteger PacketStreamHeaderLength = sizeof(uint16_t);
|
||||||
for (NSData *packet in packets) {
|
for (NSData *packet in packets) {
|
||||||
*(uint16_t *)ptr = CFSwapInt16HostToBig(packet.length);
|
*(uint16_t *)ptr = CFSwapInt16HostToBig(packet.length);
|
||||||
ptr += PacketStreamHeaderLength;
|
ptr += PacketStreamHeaderLength;
|
||||||
memcpy(ptr, packet.bytes, packet.length);
|
[PacketStream memcpyXor:ptr src:packet xorMask:xorMask];
|
||||||
ptr += packet.length;
|
ptr += packet.length;
|
||||||
}
|
}
|
||||||
return raw;
|
return raw;
|
||||||
|
|
|
@ -114,6 +114,16 @@ class ConfigurationParserTests: XCTestCase {
|
||||||
try privateTestEncryptedCertificateKey(pkcs: "8")
|
try privateTestEncryptedCertificateKey(pkcs: "8")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testXOR() throws {
|
||||||
|
let cfg = try OpenVPN.ConfigurationParser.parsed(fromLines: ["scramble xormask F"])
|
||||||
|
XCTAssertNil(cfg.warning)
|
||||||
|
XCTAssertEqual(cfg.configuration.xorMask, Character("F").asciiValue)
|
||||||
|
|
||||||
|
let cfg2 = try OpenVPN.ConfigurationParser.parsed(fromLines: ["scramble xormask FFFF"])
|
||||||
|
XCTAssertNil(cfg.warning)
|
||||||
|
XCTAssertNil(cfg2.configuration.xorMask)
|
||||||
|
}
|
||||||
|
|
||||||
private func privateTestEncryptedCertificateKey(pkcs: String) throws {
|
private func privateTestEncryptedCertificateKey(pkcs: String) throws {
|
||||||
let cfgURL = url(withName: "tunnelbear.enc.\(pkcs)")
|
let cfgURL = url(withName: "tunnelbear.enc.\(pkcs)")
|
||||||
XCTAssertThrowsError(try OpenVPN.ConfigurationParser.parsed(fromURL: cfgURL))
|
XCTAssertThrowsError(try OpenVPN.ConfigurationParser.parsed(fromURL: cfgURL))
|
||||||
|
|
Loading…
Reference in New Issue