Permalink
Browse files

Pluggable authentication modules

  • Loading branch information...
robbiehanson committed Apr 17, 2012
1 parent be5eab5 commit e29af14d7e2c64a15b20ef4aadfcb38f73701162
Showing with 1,937 additions and 1,137 deletions.
  1. +45 −0 Authentication/Anonymous/XMPPAnonymousAuthentication.h
  2. +131 −0 Authentication/Anonymous/XMPPAnonymousAuthentication.m
  3. +22 −0 Authentication/Deprecated-Digest/XMPPDeprecatedDigestAuthentication.h
  4. +162 −0 Authentication/Deprecated-Digest/XMPPDeprecatedDigestAuthentication.m
  5. +22 −0 Authentication/Deprecated-Plain/XMPPDeprecatedPlainAuthentication.h
  6. +156 −0 Authentication/Deprecated-Plain/XMPPDeprecatedPlainAuthentication.m
  7. +22 −0 Authentication/Digest-MD5/XMPPDigestMD5Authentication.h
  8. +289 −0 Authentication/Digest-MD5/XMPPDigestMD5Authentication.m
  9. +22 −0 Authentication/Plain/XMPPPlainAuthentication.h
  10. +103 −0 Authentication/Plain/XMPPPlainAuthentication.m
  11. +56 −0 Authentication/X-Facebook-Platform/XMPPXFacebookPlatformAuthentication.h
  12. +319 −0 Authentication/X-Facebook-Platform/XMPPXFacebookPlatformAuthentication.m
  13. +96 −0 Authentication/XMPPSASLAuthentication.h
  14. +20 −0 Core/XMPP.h
  15. +31 −18 Core/XMPPInternal.h
  16. +5 −1 Core/XMPPLogging.h
  17. +64 −37 Core/XMPPStream.h
  18. +163 −680 Core/XMPPStream.m
  19. +0 −43 Utilities/XMPPDigestAuthentication.h
  20. +0 −160 Utilities/XMPPDigestAuthentication.m
  21. +0 −15 Utilities/XMPPSASLAuthentication.h
  22. +0 −32 Utilities/XMPPXFacebookPlatformAuthentication.h
  23. +0 −115 Utilities/XMPPXFacebookPlatformAuthentication.m
  24. +15 −5 Xcode/DesktopXMPP/RosterController.m
  25. +96 −14 Xcode/DesktopXMPP/XMPPStream.xcodeproj/project.pbxproj
  26. +1 −1 Xcode/iPhoneXMPP/Classes/XMPPFramework.h
  27. +97 −16 Xcode/iPhoneXMPP/iPhoneXMPP.xcodeproj/project.pbxproj
@@ -0,0 +1,45 @@
+#import <Foundation/Foundation.h>
+#import "XMPPSASLAuthentication.h"
+#import "XMPP.h"
+
+
+@interface XMPPAnonymousAuthentication : NSObject <XMPPSASLAuthentication>
+
+- (id)initWithStream:(XMPPStream *)stream;
+
+// This class implements the XMPPSASLAuthentication protocol.
+//
+// See XMPPSASLAuthentication.h for more information.
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark -
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@interface XMPPStream (XMPPAnonymousAuthentication)
+
+/**
+ * Returns whether or not the server support anonymous authentication.
+ *
+ * This information is available after the stream is connected.
+ * In other words, after the delegate has received xmppStreamDidConnect: notification.
+**/
+- (BOOL)supportsAnonymousAuthentication;
+
+/**
+ * This method attempts to start the anonymous authentication process.
+ *
+ * This method is asynchronous.
+ *
+ * If there is something immediately wrong,
+ * such as the stream is not connected or doesn't support anonymous authentication,
+ * the method will return NO and set the error.
+ * Otherwise the delegate callbacks are used to communicate auth success or failure.
+ *
+ * @see xmppStreamDidAuthenticate:
+ * @see xmppStream:didNotAuthenticate:
+**/
+- (BOOL)authenticateAnonymously:(NSError **)errPtr;
+
+@end
@@ -0,0 +1,131 @@
+#import "XMPPAnonymousAuthentication.h"
+#import "XMPP.h"
+#import "XMPPLogging.h"
+#import "XMPPInternal.h"
+#import "NSXMLElement+XMPP.h"
+
+#if ! __has_feature(objc_arc)
+#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
+#endif
+
+// Log levels: off, error, warn, info, verbose
+#if DEBUG
+ static const int xmppLogLevel = XMPP_LOG_LEVEL_INFO; // | XMPP_LOG_FLAG_TRACE;
+#else
+ static const int xmppLogLevel = XMPP_LOG_LEVEL_WARN;
+#endif
+
+/**
+ * Seeing a return statements within an inner block
+ * can sometimes be mistaken for a return point of the enclosing method.
+ * This makes inline blocks a bit easier to read.
+**/
+#define return_from_block return
+
+
+@implementation XMPPAnonymousAuthentication
+{
+ #if __has_feature(objc_arc_weak)
+ __weak XMPPStream *xmppStream;
+ #else
+ __unsafe_unretained XMPPStream *xmppStream;
+ #endif
+}
+
++ (NSString *)mechanismName
+{
+ return @"ANONYMOUS";
+}
+
+- (id)initWithStream:(XMPPStream *)stream
+{
+ if ((self = [super init]))
+ {
+ xmppStream = stream;
+ }
+ return self;
+}
+
+- (id)initWithStream:(XMPPStream *)stream password:(NSString *)password
+{
+ return [self initWithStream:stream];
+}
+
+- (BOOL)start:(NSError **)errPtr
+{
+ // <auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="ANONYMOUS" />
+
+ NSXMLElement *auth = [NSXMLElement elementWithName:@"auth" xmlns:@"urn:ietf:params:xml:ns:xmpp-sasl"];
+ [auth addAttributeWithName:@"mechanism" stringValue:@"ANONYMOUS"];
+
+ [xmppStream sendAuthElement:auth];
+
+ return YES;
+}
+
+- (XMPPHandleAuthResponse)handleAuth:(NSXMLElement *)authResponse
+{
+ // We're expecting a success response.
+ // If we get anything else we can safely assume it's the equivalent of a failure response.
+
+ if ([[authResponse name] isEqualToString:@"success"])
+ {
+ return XMPP_AUTH_SUCCESS;
+ }
+ else
+ {
+ return XMPP_AUTH_FAIL;
+ }
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark -
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@implementation XMPPStream (XMPPAnonymousAuthentication)
+
+- (BOOL)supportsAnonymousAuthentication
+{
+ return [self supportsAuthenticationMechanism:[XMPPAnonymousAuthentication mechanismName]];
+}
+
+- (BOOL)authenticateAnonymously:(NSError **)errPtr
+{
+ XMPPLogTrace();
+
+ __block BOOL result = YES;
+ __block NSError *err = nil;
+
+ dispatch_block_t block = ^{ @autoreleasepool {
+
+ if ([self supportsAnonymousAuthentication])
+ {
+ XMPPAnonymousAuthentication *anonymousAuth = [[XMPPAnonymousAuthentication alloc] initWithStream:self];
+
+ result = [self authenticate:anonymousAuth error:&err];
+ }
+ else
+ {
+ NSString *errMsg = @"The server does not support anonymous authentication.";
+ NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey];
+
+ err = [NSError errorWithDomain:XMPPStreamErrorDomain code:XMPPStreamUnsupportedAction userInfo:info];
+
+ result = NO;
+ }
+ }};
+
+ if (dispatch_get_current_queue() == xmppQueue)
+ block();
+ else
+ dispatch_sync(xmppQueue, block);
+
+ if (errPtr)
+ *errPtr = err;
+
+ return result;
+}
+
+@end
@@ -0,0 +1,22 @@
+#import <Foundation/Foundation.h>
+#import "XMPPSASLAuthentication.h"
+#import "XMPPStream.h"
+
+
+@interface XMPPDeprecatedDigestAuthentication : NSObject <XMPPSASLAuthentication>
+
+// This class implements the XMPPSASLAuthentication protocol.
+//
+// See XMPPSASLAuthentication.h for more information.
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark -
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@interface XMPPStream (XMPPDeprecatedDigestAuthentication)
+
+- (BOOL)supportsDeprecatedDigestAuthentication;
+
+@end
@@ -0,0 +1,162 @@
+#import "XMPPDeprecatedDigestAuthentication.h"
+#import "XMPP.h"
+#import "XMPPInternal.h"
+#import "XMPPLogging.h"
+#import "NSData+XMPP.h"
+#import "NSXMLElement+XMPP.h"
+
+#if ! __has_feature(objc_arc)
+#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
+#endif
+
+// Log levels: off, error, warn, info, verbose
+#if DEBUG
+ static const int xmppLogLevel = XMPP_LOG_LEVEL_INFO; // | XMPP_LOG_FLAG_TRACE;
+#else
+ static const int xmppLogLevel = XMPP_LOG_LEVEL_WARN;
+#endif
+
+
+@implementation XMPPDeprecatedDigestAuthentication
+{
+ #if __has_feature(objc_arc_weak)
+ __weak XMPPStream *xmppStream;
+ #else
+ __unsafe_unretained XMPPStream *xmppStream;
+ #endif
+
+ NSString *password;
+}
+
++ (NSString *)mechanismName
+{
+ // This deprecated method isn't listed in the normal mechanisms list
+ return nil;
+}
+
+- (id)initWithStream:(XMPPStream *)stream password:(NSString *)inPassword
+{
+ if ((self = [super init]))
+ {
+ xmppStream = stream;
+ password = inPassword;
+ }
+ return self;
+}
+
+- (BOOL)start:(NSError **)errPtr
+{
+ XMPPLogTrace();
+
+ // The server does not appear to support SASL authentication (at least any type we can use)
+ // So we'll revert back to the old fashioned jabber:iq:auth mechanism
+
+ XMPPJID *myJID = xmppStream.myJID;
+
+ NSString *username = [myJID user];
+ NSString *resource = [myJID resource];
+
+ if ([resource length] == 0)
+ {
+ // If resource is nil or empty, we need to auto-create one
+
+ resource = [XMPPStream generateUUID];
+ }
+
+ NSString *rootID = [[[xmppStream rootElement] attributeForName:@"id"] stringValue];
+ NSString *digestStr = [NSString stringWithFormat:@"%@%@", rootID, password];
+
+ NSString *digest = [[[digestStr dataUsingEncoding:NSUTF8StringEncoding] sha1Digest] hexStringValue];
+
+ NSXMLElement *query = [NSXMLElement elementWithName:@"query" xmlns:@"jabber:iq:auth"];
+ [query addChild:[NSXMLElement elementWithName:@"username" stringValue:username]];
+ [query addChild:[NSXMLElement elementWithName:@"resource" stringValue:resource]];
+ [query addChild:[NSXMLElement elementWithName:@"digest" stringValue:digest]];
+
+ XMPPIQ *iq = [XMPPIQ iqWithType:@"set"];
+ [iq addChild:query];
+
+ [xmppStream sendAuthElement:iq];
+
+ return YES;
+}
+
+- (XMPPHandleAuthResponse)handleAuth:(NSXMLElement *)authResponse
+{
+ XMPPLogTrace();
+
+ // We used the old fashioned jabber:iq:auth mechanism
+
+ if ([[authResponse attributeStringValueForName:@"type"] isEqualToString:@"error"])
+ {
+ return XMPP_AUTH_FAIL;
+ }
+ else
+ {
+ return XMPP_AUTH_SUCCESS;
+ }
+}
+
+- (BOOL)shouldResendOpeningNegotiationAfterSuccessfulAuthentication
+{
+ return NO;
+}
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark -
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@implementation XMPPStream (XMPPDeprecatedDigestAuthentication)
+
+/**
+ * This method only applies to servers that don't support XMPP version 1.0, as defined in RFC 3920.
+ * With these servers, we attempt to discover supported authentication modes via the jabber:iq:auth namespace.
+**/
+- (BOOL)supportsDeprecatedDigestAuthentication
+{
+ __block BOOL result = NO;
+
+ dispatch_block_t block = ^{ @autoreleasepool {
+
+ // The root element can be properly queried for authentication mechanisms anytime after the
+ // stream:features are received, and TLS has been setup (if required)
+ if (state >= STATE_XMPP_POST_NEGOTIATION)
+ {
+ // Search for an iq element within the rootElement.
+ // Recall that some servers might stupidly add a "jabber:client" namespace which might cause problems
+ // if we simply used the elementForName method.
+
+ NSXMLElement *iq = nil;
+
+ NSUInteger i, count = [rootElement childCount];
+ for (i = 0; i < count; i++)
+ {
+ NSXMLNode *childNode = [rootElement childAtIndex:i];
+
+ if ([childNode kind] == NSXMLElementKind)
+ {
+ if ([[childNode name] isEqualToString:@"iq"])
+ {
+ iq = (NSXMLElement *)childNode;
+ }
+ }
+ }
+
+ NSXMLElement *query = [iq elementForName:@"query" xmlns:@"jabber:iq:auth"];
+ NSXMLElement *digest = [query elementForName:@"digest"];
+
+ result = (digest != nil);
+ }
+ }};
+
+ if (dispatch_get_current_queue() == xmppQueue)
+ block();
+ else
+ dispatch_sync(xmppQueue, block);
+
+ return result;
+}
+
+@end
@@ -0,0 +1,22 @@
+#import <Foundation/Foundation.h>
+#import "XMPPSASLAuthentication.h"
+#import "XMPPStream.h"
+
+
+@interface XMPPDeprecatedPlainAuthentication : NSObject <XMPPSASLAuthentication>
+
+// This class implements the XMPPSASLAuthentication protocol.
+//
+// See XMPPSASLAuthentication.h for more information.
+
+@end
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark -
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+@interface XMPPStream (XMPPDeprecatedPlainAuthentication)
+
+- (BOOL)supportsDeprecatedPlainAuthentication;
+
+@end
Oops, something went wrong.

0 comments on commit e29af14

Please sign in to comment.