Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #206 (Implement SRV lookup) #385

Merged
merged 36 commits into from
Apr 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
8232580
Fix utf-8 decoding error DOS vector
tmolitor-stud-tu Mar 22, 2020
13760b1
Fix all kinds of state related bugs (carbons etc.)
tmolitor-stud-tu Mar 22, 2020
4693167
fixed logic and builds
Mar 22, 2020
a32bdbf
Try to fix multicarbon issue and add more logging
tmolitor-stud-tu Mar 22, 2020
c54b585
update active chat with own messages
Mar 23, 2020
0e20064
Fix ambiguous column name
FriedrichAltheide Mar 26, 2020
f95f570
Try to fix smacks request bug
tmolitor-stud-tu Mar 26, 2020
605ea3e
Make outputBuffer dynamic in size
tmolitor-stud-tu Mar 26, 2020
66c4e38
Fix smacks request bug this time for sure
tmolitor-stud-tu Mar 26, 2020
c48b34a
show correct message timestamp
Mar 26, 2020
a0218c0
Allow jid as roster source
FriedrichAltheide Mar 26, 2020
c6f4f3a
!= nil
FriedrichAltheide Mar 26, 2020
90f5ca0
Basic message draft support (#382)
FriedrichAltheide Mar 28, 2020
c77fcaa
dont block main thread
Mar 28, 2020
b238913
stanzaid
Mar 28, 2020
bf2f968
typo
Mar 28, 2020
fdfbd2d
Implement XEP-0368, fixes #206
tmolitor-stud-tu Mar 27, 2020
61313b9
Make database access concurrent
tmolitor-stud-tu Mar 29, 2020
fa9219f
Revert "dont block main thread"
tmolitor-stud-tu Mar 29, 2020
ba8a29f
Fix crash when registering new account via QuickSetup
tmolitor-stud-tu Mar 31, 2020
15ae340
remove help
Apr 3, 2020
7c90556
Create XEPsupport.md
Echolon Apr 4, 2020
57d7c96
Update ReadMe.md
Echolon Apr 4, 2020
3aa0c6b
Update XEPsupport.md
Echolon Apr 4, 2020
27f393a
Update XEPsupport.md
Echolon Apr 4, 2020
7938a84
Update XEPsupport.md
Echolon Apr 4, 2020
01ef882
Minor XEPSupport.md fix.
marmistrz Apr 4, 2020
f8058b6
text fix
Apr 5, 2020
2f42c8f
super view did load
Apr 12, 2020
c1bf35e
v 4.6
Apr 12, 2020
5fe642c
super ugly but allows presence inside presence for now.
Apr 12, 2020
cd351c4
dont crash
Apr 12, 2020
fb1cf29
Fix #370 (#388)
FriedrichAltheide Apr 12, 2020
fefdc6a
display geo location (#390)
FriedrichAltheide Apr 13, 2020
57d379f
Revert "text fix"
tmolitor-stud-tu Apr 13, 2020
4bd600b
Merge branch 'develop' into develop
tmolitor-stud-tu Apr 13, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,159 changes: 608 additions & 551 deletions Monal/Classes/DataLayer.m

Large diffs are not rendered by default.

25 changes: 17 additions & 8 deletions Monal/Classes/MLDNSLookup.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,19 @@
@import Darwin.POSIX.sys.time;

@interface MLDNSLookup()

@end

BOOL isSecure=NO;

@implementation MLDNSLookup

-(NSArray *) dnsDiscoverOnDomain:(NSString *) domain
-(void) doDiscoveryWithSecure: (BOOL)secure andDomain: (NSString *) domain
{
self.discoveredServers =[[NSMutableArray alloc] init];

DNSServiceRef sdRef;
DNSServiceRef sdRef;
DNSServiceErrorType res;

NSString* serviceDiscoveryString=[NSString stringWithFormat:@"_xmpp-client._tcp.%@", domain];

isSecure = secure;
NSString* serviceDiscoveryString=[NSString stringWithFormat:@"_xmpp%s-client._tcp.%@", isSecure ? "s" : "", domain];
res=DNSServiceQueryRecord(
&sdRef, 0, 0,
[serviceDiscoveryString UTF8String],
Expand Down Expand Up @@ -63,7 +62,17 @@ -(NSArray *) dnsDiscoverOnDomain:(NSString *) domain
}

}
}

-(NSArray *) dnsDiscoverOnDomain:(NSString *) domain
{
self.discoveredServers =[[NSMutableArray alloc] init];

//mix xmpps and xmpp records as per XEP-0368
[self doDiscoveryWithSecure:YES andDomain:domain];
[self doDiscoveryWithSecure:NO andDomain:domain];

//we ignore weights here for simplicity
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"priority" ascending:YES];
NSArray* sortArray =[NSArray arrayWithObjects:descriptor,nil];
[self.discoveredServers sortUsingDescriptors:sortArray];
Expand Down Expand Up @@ -143,7 +152,7 @@ void print_rdata(int type, int len, const u_char *rdata, void* context)
NSNumber* num=[NSNumber numberWithInt:ntohs(srv->priority)];
NSNumber* theport=[NSNumber numberWithInt:portval];
if(theserver && num && theport) {
NSDictionary* row=[NSDictionary dictionaryWithObjectsAndKeys:num,@"priority", theserver, @"server", theport, @"port",nil];
NSDictionary* row=[NSDictionary dictionaryWithObjectsAndKeys:num,@"priority", theserver,@"server", theport,@"port", [NSNumber numberWithBool:isSecure],@"isSecure", nil];
[caller.discoveredServers addObject:row];
}
}
Expand Down
3 changes: 1 addition & 2 deletions Monal/Classes/MLRegisterViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,10 @@ -(void) makeXMPPConnection {

MLXMPPIdentity *identity = [[MLXMPPIdentity alloc] initWithJid:@"nothing@yax.im" password:@"nothing" andResource:@"MonalReg"];

MLXMPPServer *server = [[MLXMPPServer alloc] initWithHost:kRegServer andPort:[NSNumber numberWithInt:5222]];
MLXMPPServer *server = [[MLXMPPServer alloc] initWithHost:kRegServer andPort:[NSNumber numberWithInt:5222] andOldStyleSSL:NO];

server.SSL=YES;
server.selfSignedCert=NO;
server.oldStyleSSL=NO;

self.xmppAccount= [[xmpp alloc] initWithServer:server andIdentity:identity];

Expand Down
3 changes: 1 addition & 2 deletions Monal/Classes/MLXMPPManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -299,10 +299,9 @@ -(void) connectAccountWithDictionary:(NSDictionary*)account
NSString *password = [SAMKeychain passwordForService:@"Monal" account:[NSString stringWithFormat:@"%@",[account objectForKey:kAccountID]]];
MLXMPPIdentity *identity = [[MLXMPPIdentity alloc] initWithJid:[NSString stringWithFormat:@"%@@%@",[account objectForKey:kUsername],[account objectForKey:kDomain] ] password:password andResource:[account objectForKey:kResource]];

MLXMPPServer *server = [[MLXMPPServer alloc] initWithHost:[account objectForKey:kServer] andPort:[account objectForKey:kPort]];
MLXMPPServer *server = [[MLXMPPServer alloc] initWithHost:[account objectForKey:kServer] andPort:[account objectForKey:kPort] andOldStyleSSL:[[account objectForKey:kOldSSL] boolValue]];

server.SSL=[[account objectForKey:kSSL] boolValue];
server.oldStyleSSL=[[account objectForKey:kOldSSL] boolValue];
server.selfSignedCert=[[account objectForKey:kSelfSigned] boolValue];

if(server.oldStyleSSL && !server.SSL ) server.SSL=YES; //tehcnically a config error but understandable
Expand Down
9 changes: 8 additions & 1 deletion Monal/Classes/MLXMPPServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic,assign) BOOL oldStyleSSL;
@property (nonatomic,assign) BOOL selfSignedCert;

-(id) initWithHost:(NSString *) host andPort:(NSNumber *) port;
-(id) initWithHost:(NSString *) host andPort:(NSNumber *) port andOldStyleSSL:(BOOL) oldStyleSSL;


- (void) updateConnectServer:(NSString *) server;

- (void) updateConnectPort:(NSNumber *) port;

- (void) updateConnectTLS:(BOOL) isSecure;

/**
returns the currently connected server may be host or dns one.
*/
Expand All @@ -39,6 +41,11 @@ returns the currently connected port may be configured or dns one.
*/
- (NSNumber *) connectPort;

/**
returns the currently directTLS setting may be configured or dns one.
*/
- (BOOL) connectTLS;

@end

NS_ASSUME_NONNULL_END
14 changes: 13 additions & 1 deletion Monal/Classes/MLXMPPServer.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,21 @@ @interface MLXMPPServer ()
*/
@property (nonatomic, strong) NSString *serverInUse;
@property (nonatomic, strong) NSNumber *portInUse;
@property (nonatomic, assign) BOOL directTLSInUse;

@end

@implementation MLXMPPServer

-(id) initWithHost:(NSString *) host andPort:(NSNumber *) port{
-(id) initWithHost:(NSString *) host andPort:(NSNumber *) port andOldStyleSSL:(BOOL) oldStyleSSL {
self = [super init];
self.host=host;
self.port=port;
self.oldStyleSSL=oldStyleSSL;

self.serverInUse=host;
self.portInUse=port;
self.directTLSInUse=oldStyleSSL;

return self;
}
Expand All @@ -56,4 +59,13 @@ - (NSNumber *) connectPort {
return self.portInUse;
}

- (void) updateConnectTLS:(BOOL) isSecure
{
self.directTLSInUse = isSecure;
}

- (BOOL) connectTLS {
return self.directTLSInUse;
}

@end
3 changes: 2 additions & 1 deletion Monal/Classes/xmpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ typedef void (^xmppDataCompletion)(NSData *captchaImage, NSDictionary *hiddenFie
@property (nonatomic, readonly) xmppState accountState;

// discovered properties
@property (nonatomic,strong) NSArray* discoveredServerList;
@property (nonatomic,strong) NSArray* discoveredServersList;
@property (nonatomic,strong) NSMutableArray* usableServersList;

@property (nonatomic,strong) NSArray* roomList;
@property (nonatomic, strong) NSArray* rosterList;
Expand Down
157 changes: 88 additions & 69 deletions Monal/Classes/xmpp.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

#import <CommonCrypto/CommonCrypto.h>
#import <CFNetwork/CFSocketStream.h>
#import <Security/SecureTransport.h>

#import "xmpp.h"
#import "DataLayer.h"
#import "EncodingTools.h"
Expand Down Expand Up @@ -156,7 +158,9 @@ -(void) setupObjects
{
_accountState = kStateLoggedOut;

_discoveredServerList=[[NSMutableArray alloc] init];
_discoveredServersList=[[NSMutableArray alloc] init];
if(!_usableServersList)
_usableServersList=[[NSMutableArray alloc] init];
_inputDataBuffer=[[NSMutableData alloc] init];
_inputBuffer=[[NSMutableString alloc] init];
_outputQueue=[[NSMutableArray alloc] init];
Expand Down Expand Up @@ -242,14 +246,45 @@ -(void) setRunLoop
[_iStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
}

-(void) initTLS
{
NSMutableDictionary *settings = [[NSMutableDictionary alloc] init];
[settings setObject:self.connectionProperties.identity.domain forKey:kCFStreamSSLPeerName];
if(self.connectionProperties.server.selfSignedCert)
{
DDLogInfo(@"configured self signed SSL");
[settings setObject:@NO forKey:kCFStreamSSLValidatesCertificateChain];
}

//this will create an sslContext and, if the underlying TCP socket is already connected, immediately start the ssl handshake
DDLogInfo(@"configuring SSL handshake");
if(CFReadStreamSetProperty((__bridge CFReadStreamRef)self->_iStream, kCFStreamPropertySSLSettings, (__bridge CFTypeRef)settings))
DDLogInfo(@"Set TLS properties on streams. Security level %@", [self->_iStream propertyForKey:NSStreamSocketSecurityLevelKey]);
else
{
DDLogError(@"not sure.. Could not confirm Set TLS properties on streams.");
DDLogInfo(@"Set TLS properties on streams.security level %@", [self->_iStream propertyForKey:NSStreamSocketSecurityLevelKey]);
}

//see this for extracting the sslcontext of the cfstream: https://stackoverflow.com/a/26726525/3528174
//see this for creating the proper protocols array: https://github.com/LLNL/FRS/blob/master/Pods/AWSIoT/AWSIoT/Internal/AWSIoTMQTTClient.m
//this will only have an effect if the TLS handshake was not already started (e.g. the TCP socket is not connected)
SSLContextRef sslContext = (__bridge SSLContextRef) [_iStream propertyForKey: (__bridge NSString *) kCFStreamPropertySSLContext ];
CFStringRef strs[1];
strs[0] = CFSTR("xmpp-client");
CFArrayRef protocols = CFArrayCreate(NULL, (void *)strs, 1, &kCFTypeArrayCallBacks);
SSLSetALPNProtocols(sslContext, protocols);
CFRelease(protocols);
}

-(void) createStreams
{
DDLogInfo(@"stream creating to server: %@ port: %@", self.connectionProperties.server.connectServer, self.connectionProperties.server.port);
DDLogInfo(@"stream creating to server: %@ port: %@ directTLS: %@", self.connectionProperties.server.connectServer, self.connectionProperties.server.connectPort, self.connectionProperties.server.connectTLS ? @"YES" : @"NO");

NSInputStream *localIStream;
NSOutputStream *localOStream;

[NSStream getStreamsToHostWithName:self.connectionProperties.server.connectServer port:self.connectionProperties.server.port.integerValue inputStream:&localIStream outputStream:&localOStream];
[NSStream getStreamsToHostWithName:self.connectionProperties.server.connectServer port:self.connectionProperties.server.connectPort.integerValue inputStream:&localIStream outputStream:&localOStream];

if(localIStream) {
_iStream=localIStream;
Expand All @@ -276,37 +311,10 @@ -(void) createStreams
DDLogInfo(@"streams created ok");
}


if((self.connectionProperties.server.SSL==YES) && (self.connectionProperties.server.oldStyleSSL==YES))
if(self.connectionProperties.server.connectTLS==YES)
{
// do ssl stuff here
DDLogInfo(@"starting old style SSL");

NSMutableDictionary *settings = [ [NSMutableDictionary alloc ]
initWithObjectsAndKeys:
kCFStreamSocketSecurityLevelNegotiatedSSL,
kCFStreamSSLLevel,
nil ];

if(self.connectionProperties.server.selfSignedCert)
{
DDLogInfo(@"self signed SSL");
NSDictionary* secureOFF= [ [NSDictionary alloc ]
initWithObjectsAndKeys:
[NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain, nil];

[settings addEntriesFromDictionary:secureOFF];



}

CFReadStreamSetProperty((__bridge CFReadStreamRef)_iStream,
kCFStreamPropertySSLSettings, (__bridge CFTypeRef)settings);
CFWriteStreamSetProperty((__bridge CFWriteStreamRef)_oStream,
kCFStreamPropertySSLSettings, (__bridge CFTypeRef)settings);

DDLogInfo(@"connection secured");
DDLogInfo(@"starting directSSL");
[self initTLS];
}

MLXMLNode* xmlOpening = [[MLXMLNode alloc] initWithElement:@"xml"];
Expand All @@ -315,8 +323,7 @@ -(void) createStreams
[self setRunLoop];

dispatch_queue_t q_background = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t streamTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,q_background
);
dispatch_source_t streamTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,q_background);

dispatch_source_set_timer(streamTimer,
dispatch_time(DISPATCH_TIME_NOW, 5ull * NSEC_PER_SEC),
Expand Down Expand Up @@ -347,16 +354,49 @@ -(void) createStreams

-(void) connectionTask
{
if(self.connectionProperties.server.oldStyleSSL==NO) {
// do DNS discovery if it hasn't already been set
if([_discoveredServerList count]==0) {
_discoveredServerList= [[[MLDNSLookup alloc] init] dnsDiscoverOnDomain:self.connectionProperties.identity.domain];
}
// do DNS discovery if it hasn't already been set
if([_discoveredServersList count]==0) {
_discoveredServersList=[[[MLDNSLookup alloc] init] dnsDiscoverOnDomain:self.connectionProperties.identity.domain];
}

if([_discoveredServerList count]>0) {
[self.connectionProperties.server updateConnectServer:[[_discoveredServerList objectAtIndex:0] objectForKey:@"server"]];
[self.connectionProperties.server updateConnectPort:[[_discoveredServerList objectAtIndex:0] objectForKey:@"port"]];
//if all servers have been tried start over with the first one again
if([_discoveredServersList count]>0 && [_usableServersList count]==0)
{
DDLogWarn(@"All %lu SRV dns records tried, starting over again", (unsigned long)[_discoveredServersList count]);
_usableServersList = [_discoveredServersList mutableCopy];
for(NSDictionary *row in _usableServersList)
{
DDLogInfo(@"SRV entry: server=%@, port=%@, isSecure=%s (prio: %@)",
[row objectForKey:@"server"],
[row objectForKey:@"port"],
[[row objectForKey:@"isSecure"] boolValue] ? "YES" : "NO",
[row objectForKey:@"priority"]
);
}
}

if([_usableServersList count]>0) {
DDLogInfo(@"Using connection parameters discovered via SRV dns record: server=%@, port=%@, isSecure=%s, priority=%@",
[[_usableServersList objectAtIndex:0] objectForKey:@"server"],
[[_usableServersList objectAtIndex:0] objectForKey:@"port"],
[[[_usableServersList objectAtIndex:0] objectForKey:@"isSecure"] boolValue] ? "YES" : "NO",
[[_usableServersList objectAtIndex:0] objectForKey:@"priority"]
);
[self.connectionProperties.server updateConnectServer: [[_usableServersList objectAtIndex:0] objectForKey:@"server"]];
[self.connectionProperties.server updateConnectPort: [[_usableServersList objectAtIndex:0] objectForKey:@"port"]];
[self.connectionProperties.server updateConnectTLS: [[[_usableServersList objectAtIndex:0] objectForKey:@"isSecure"] boolValue]];
//remove this server so that the next connection attempt will try the next server in the list
[_usableServersList removeObjectAtIndex:0];
DDLogInfo(@"%lu SRV entries left:", (unsigned long)[_usableServersList count]);
for(NSDictionary *row in _usableServersList)
{
DDLogInfo(@"SRV entry: server=%@, port=%@, isSecure=%s (prio: %@)",
[row objectForKey:@"server"],
[row objectForKey:@"port"],
[[row objectForKey:@"isSecure"] boolValue] ? "YES" : "NO",
[row objectForKey:@"priority"]
);
}
}

[self createStreams];
Expand Down Expand Up @@ -1190,7 +1230,7 @@ -(void) requestSMAck
[self send:rNode];
self.smacksRequestInFlight=YES;
} else {
DDLogDebug(@"no smacks ack when there is nothing pending or a request already in flight...");
DDLogDebug(@"no smacks request, there is nothing pending or a request already in flight...");
}
}

Expand Down Expand Up @@ -1563,7 +1603,7 @@ -(void) processInput

if ((self.connectionProperties.server.SSL && self->_startTLSComplete)
|| (!self.connectionProperties.server.SSL && !self->_startTLSComplete)
|| (self.connectionProperties.server.SSL && self.connectionProperties.server.oldStyleSSL))
|| (self.connectionProperties.server.connectTLS==YES))
{
if(self.registration){
[self requestRegForm];
Expand Down Expand Up @@ -1778,30 +1818,7 @@ -(void) processInput
{
if(streamNode.startTLSProceed)
{
NSMutableDictionary *settings = [[NSMutableDictionary alloc] init];
[settings setObject:self.connectionProperties.identity.domain forKey:kCFStreamSSLPeerName];

[settings setObject:kCFStreamSocketSecurityLevelNegotiatedSSL forKey:kCFStreamSSLLevel];

if(self.connectionProperties.server.selfSignedCert)
{
[settings setObject:@NO forKey:kCFStreamSSLValidatesCertificateChain];
}

if (CFReadStreamSetProperty((__bridge CFReadStreamRef)self->_iStream,
kCFStreamPropertySSLSettings, (__bridge CFTypeRef)settings) &&
CFWriteStreamSetProperty((__bridge CFWriteStreamRef)self->_oStream,
kCFStreamPropertySSLSettings, (__bridge CFTypeRef)settings))

{
DDLogInfo(@"Set TLS properties on streams. Security level %@", [self->_iStream propertyForKey:NSStreamSocketSecurityLevelKey]);

}
else
{
DDLogError(@"not sure.. Could not confirm Set TLS properties on streams.");
DDLogInfo(@"Set TLS properties on streams.security level %@", [self->_iStream propertyForKey:NSStreamSocketSecurityLevelKey]);
}
[self initTLS];

[self startStream];

Expand Down Expand Up @@ -1963,6 +1980,8 @@ -(void) processInput
self->_loginStarted=NO;
self.loginStartTimeStamp=nil;

//reset usable servers list so that the next connect starts with the highest prio server again
_usableServersList=[[NSMutableArray alloc] init];

}
}
Expand Down
2 changes: 1 addition & 1 deletion Monal/Monal Tests/XMPP Tests/MLIQParserTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ - (void)setUp {

MLXMPPIdentity *identity = [[MLXMPPIdentity alloc] initWithJid:self.jid password:@"" andResource:self.resource];

MLXMPPServer *server = [[MLXMPPServer alloc] initWithHost:@"monal.im" andPort:@5222];
MLXMPPServer *server = [[MLXMPPServer alloc] initWithHost:@"monal.im" andPort:@5222 andOldStyleSSL:NO];
server.SSL=YES;

self.connectionProperties = [[MLXMPPConnection alloc] initWithServer:server andIdentity:identity];
Expand Down
Loading