Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mumble-voip/mumblekit.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikkel Krautz <mikkel@krautz.dk>2012-04-08 01:43:25 +0400
committerMikkel Krautz <mikkel@krautz.dk>2012-04-08 01:43:25 +0400
commita975ad3fd53d4ec0506fd32d0d43673e38aa7d70 (patch)
treebbb7dfcce150e6e21120dcef39b9b72ab6b8df3e
parentc9edba9ac283afd87ccee4a8da0deeee608589f5 (diff)
MKCertificate, MKDistinguishedNameParser: implement and use DN parser.
-rw-r--r--MumbleKit.xcodeproj/project.pbxproj12
-rw-r--r--src/MKCertificate.m25
-rw-r--r--src/MKDistinguishedNameParser.h7
-rw-r--r--src/MKDistinguishedNameParser.m238
4 files changed, 261 insertions, 21 deletions
diff --git a/MumbleKit.xcodeproj/project.pbxproj b/MumbleKit.xcodeproj/project.pbxproj
index d7f2e26..d725889 100644
--- a/MumbleKit.xcodeproj/project.pbxproj
+++ b/MumbleKit.xcodeproj/project.pbxproj
@@ -9,6 +9,10 @@
/* Begin PBXBuildFile section */
2808DD9413E4D8C0008448EA /* MKPacketDataStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 2845A7D1132D9C520034D631 /* MKPacketDataStream.h */; };
2810DED514EA81D7004482F4 /* libCELT-0.7.0.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 28492310132ED60700B4EAAC /* libCELT-0.7.0.a */; };
+ 281EADA51530EA30000793AB /* MKDistinguishedNameParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 281EADA31530EA30000793AB /* MKDistinguishedNameParser.h */; };
+ 281EADA61530EA30000793AB /* MKDistinguishedNameParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 281EADA31530EA30000793AB /* MKDistinguishedNameParser.h */; };
+ 281EADA71530EA30000793AB /* MKDistinguishedNameParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 281EADA41530EA30000793AB /* MKDistinguishedNameParser.m */; };
+ 281EADA81530EA30000793AB /* MKDistinguishedNameParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 281EADA41530EA30000793AB /* MKDistinguishedNameParser.m */; };
282F6B0813624187008F555B /* MKServerPinger.h in Headers */ = {isa = PBXBuildFile; fileRef = 282F6B0613624187008F555B /* MKServerPinger.h */; };
282F6B0913624187008F555B /* MKServerPinger.h in Headers */ = {isa = PBXBuildFile; fileRef = 282F6B0613624187008F555B /* MKServerPinger.h */; settings = {ATTRIBUTES = (Public, ); }; };
282F6B0A13624187008F555B /* MKServerPinger.m in Sources */ = {isa = PBXBuildFile; fileRef = 282F6B0713624187008F555B /* MKServerPinger.m */; };
@@ -306,6 +310,8 @@
2815C4E0150D559800136082 /* BetaDist.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = BetaDist.xcconfig; path = cfg/BetaDist.xcconfig; sourceTree = "<group>"; };
2815C4E1150D559800136082 /* Release.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = cfg/Release.xcconfig; sourceTree = "<group>"; };
2815C4E6150D55BC00136082 /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = cfg/Debug.xcconfig; sourceTree = "<group>"; };
+ 281EADA31530EA30000793AB /* MKDistinguishedNameParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MKDistinguishedNameParser.h; path = src/MKDistinguishedNameParser.h; sourceTree = SOURCE_ROOT; };
+ 281EADA41530EA30000793AB /* MKDistinguishedNameParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MKDistinguishedNameParser.m; path = src/MKDistinguishedNameParser.m; sourceTree = SOURCE_ROOT; };
282F6B0613624187008F555B /* MKServerPinger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MKServerPinger.h; path = src/MumbleKit/MKServerPinger.h; sourceTree = SOURCE_ROOT; };
282F6B0713624187008F555B /* MKServerPinger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MKServerPinger.m; path = src/MKServerPinger.m; sourceTree = SOURCE_ROOT; };
283363DC13EF535B00A04F04 /* MKChannelPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MKChannelPrivate.h; path = src/MKChannelPrivate.h; sourceTree = SOURCE_ROOT; };
@@ -482,6 +488,7 @@
2845A792132D9C220034D631 /* MKVersion.m */,
2845A793132D9C220034D631 /* MulticastDelegate.m */,
2879526114C1BAB900567430 /* MKTextMessage.m */,
+ 281EADA41530EA30000793AB /* MKDistinguishedNameParser.m */,
);
name = Sources;
sourceTree = "<group>";
@@ -520,6 +527,7 @@
2845A7D1132D9C520034D631 /* MKPacketDataStream.h */,
283363DC13EF535B00A04F04 /* MKChannelPrivate.h */,
283363DE13EF536C00A04F04 /* MKUserPrivate.h */,
+ 281EADA31530EA30000793AB /* MKDistinguishedNameParser.h */,
);
name = "Private Headers";
sourceTree = "<group>";
@@ -658,6 +666,7 @@
28F2FAD613E37BA000034BF2 /* MKAudioOutputUserPrivate.h in Headers */,
2808DD9413E4D8C0008448EA /* MKPacketDataStream.h in Headers */,
2879526914C1BDD800567430 /* MKTextMessage.h in Headers */,
+ 281EADA61530EA30000793AB /* MKDistinguishedNameParser.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -688,6 +697,7 @@
28F2FAD513E37BA000034BF2 /* MKAudioOutputUserPrivate.h in Headers */,
283363DD13EF535B00A04F04 /* MKChannelPrivate.h in Headers */,
2879526814C1BDD800567430 /* MKTextMessage.h in Headers */,
+ 281EADA51530EA30000793AB /* MKDistinguishedNameParser.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -916,6 +926,7 @@
28CC36FD132ED92500241269 /* ObjectivecDescriptor.pb.m in Sources */,
282F6B0B13624187008F555B /* MKServerPinger.m in Sources */,
2879526514C1BAB900567430 /* MKTextMessage.m in Sources */,
+ 281EADA81530EA30000793AB /* MKDistinguishedNameParser.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -944,6 +955,7 @@
28CC36FC132ED92500241269 /* ObjectivecDescriptor.pb.m in Sources */,
282F6B0A13624187008F555B /* MKServerPinger.m in Sources */,
2879526414C1BAB900567430 /* MKTextMessage.m in Sources */,
+ 281EADA71530EA30000793AB /* MKDistinguishedNameParser.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/src/MKCertificate.m b/src/MKCertificate.m
index d7c3d5c..4a018fd 100644
--- a/src/MKCertificate.m
+++ b/src/MKCertificate.m
@@ -3,6 +3,7 @@
// license that can be found in the LICENSE file.
#import <MumbleKit/MKCertificate.h>
+#import "MKDistinguishedNameParser.h"
#include <openssl/evp.h>
#include <openssl/err.h>
@@ -310,24 +311,6 @@ static int add_ext(X509 * crt, int nid, char *value) {
return _derPrivKey != nil;
}
-// Parse a one-line UTF8 representation of subject or issuer info
-// from a certificate. Returns a dictionary with the keys and values
-// as-is.
-- (NSDictionary *) copyDictForOneLineUTF8Repr:(NSData *)data {
- NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
- NSString *str = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
- NSArray *components = [str componentsSeparatedByString:@", "];
- for (NSString *component in components) {
- NSArray *pairs = [component componentsSeparatedByString:@" = "];
- if ([pairs count] != 2) {
- [dict release];
- return nil;
- }
- [dict setObject:[pairs objectAtIndex:1] forKey:[pairs objectAtIndex:0]];
- }
- return dict;
-}
-
// Parse an ASN1 string representing time from an X509 PKIX certificate.
- (NSDate *) copyAndParseASN1Date:(ASN1_TIME *)time {
struct tm tm;
@@ -395,7 +378,7 @@ static int add_ext(X509 * crt, int nid, char *value) {
BUF_MEM *buf = NULL;
BIO_get_mem_ptr(mem, &buf);
NSData *data = [[NSData alloc] initWithBytes:buf->data length:buf->length];
- _subjectDict = [self copyDictForOneLineUTF8Repr:data];
+ _subjectDict = [[MKDistinguishedNameParser parseName:data] retain];
[data release];
}
BIO_free(mem);
@@ -409,7 +392,7 @@ static int add_ext(X509 * crt, int nid, char *value) {
BUF_MEM *buf = NULL;
BIO_get_mem_ptr(mem, &buf);
NSData *data = [[NSData alloc] initWithBytesNoCopy:buf->data length:buf->length freeWhenDone:NO];
- _issuerDict = [self copyDictForOneLineUTF8Repr:data];
+ _issuerDict = [[MKDistinguishedNameParser parseName:data] retain];
[data release];
}
BIO_free(mem);
@@ -637,4 +620,4 @@ static int add_ext(X509 * crt, int nid, char *value) {
return _privateKey;
}
-@end
+@end \ No newline at end of file
diff --git a/src/MKDistinguishedNameParser.h b/src/MKDistinguishedNameParser.h
new file mode 100644
index 0000000..ff9cbda
--- /dev/null
+++ b/src/MKDistinguishedNameParser.h
@@ -0,0 +1,7 @@
+// Copyright 2012 The MumbleKit Developers. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+@interface MKDistinguishedNameParser : NSObject
++ (NSDictionary *) parseName:(NSData *)dn;
+@end \ No newline at end of file
diff --git a/src/MKDistinguishedNameParser.m b/src/MKDistinguishedNameParser.m
new file mode 100644
index 0000000..1a2a31e
--- /dev/null
+++ b/src/MKDistinguishedNameParser.m
@@ -0,0 +1,238 @@
+// Copyright 2012 The MumbleKit Developers. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#import "MKDistinguishedNameParser.h"
+
+@interface MKDistinguishedNameParser () {
+ NSString *_name;
+ NSInteger _pos;
+ NSMutableArray *_pairs;
+ NSMutableArray *_put;
+}
+- (id) initWithName:(NSData *)dn;
+
+- (void) parse;
+- (NSDictionary *) dictionaryRepresentation;
+
+- (unichar) getch;
+- (void) putch:(unichar)c;
+- (void) rejectWithReason:(NSString *)msg;
+
+- (void) scanAttribute;
+- (void) scanAttributeName;
+- (void) scanWhitespace;
+- (void) scanAttributeValue;
+- (void) scanCharater:(NSString *)str;
+- (void) scanEquals;
+- (void) scanComma;
+- (void) scanAttributeValue;
+- (NSString *) scanQuotedStringWithCharactersFromSet:(NSCharacterSet *)charSet;
+@end
+
+@implementation MKDistinguishedNameParser
+
++ (NSDictionary *) parseName:(NSData *)dn {
+ MKDistinguishedNameParser *parser = [[[MKDistinguishedNameParser alloc] initWithName:dn] autorelease];
+ [parser parse];
+ return [parser dictionaryRepresentation];
+}
+
+- (id) initWithName:(NSData *)dn {
+ if ((self = [super init])) {
+ // add a junk 0 char at the end of the string to ensure termination of the scanner
+ unichar nul = 0;
+ NSMutableString *nameString = [[NSMutableString alloc] initWithData:dn encoding:NSUTF8StringEncoding];
+ [nameString appendString:[NSString stringWithCharacters:&nul length:1]];
+ _name = nameString;
+ _pairs = [[NSMutableArray alloc] init];
+ _put = [[NSMutableArray alloc] init];
+ _pos = 0;
+ }
+ return self;
+}
+
+- (void) dealloc {
+ [_pairs release];
+ [_name release];
+ [_put release];
+ [super dealloc];
+}
+
+- (void) parse {
+ while (1) {
+ @try {
+ [self scanAttribute];
+ }
+ @catch (NSException *exception) {
+ return;
+ }
+ }
+}
+
+- (NSDictionary *) dictionaryRepresentation {
+ if (([_pairs count] % 2) != 0) {
+ return nil;
+ }
+ NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:[_pairs count]/2];
+ for (int i = 0; i < [_pairs count]; i += 2) {
+ [dict setObject:[_pairs objectAtIndex:i+1] forKey:[_pairs objectAtIndex:i]];
+ }
+ return dict;
+}
+
+- (unichar) getch {
+ NSInteger putCount = [_put count];
+ if (putCount > 0) {
+ unsigned long c = [[_put objectAtIndex:putCount-1] unsignedLongValue];
+ [_put removeObjectAtIndex:putCount-1];
+ return (unichar) c;
+ }
+ if (_pos > [_name length]-1) {
+ [self rejectWithReason:@"no more characters in string"];
+ }
+ return [_name characterAtIndex:_pos++];
+}
+
+- (void) putch:(unichar)c {
+ [_put addObject:[NSNumber numberWithUnsignedLong:c]];
+}
+
+- (void) rejectWithReason:(NSString *)msg {
+ [NSException raise:@"MKDistinguishedNameParserException" format:@"%@", msg];
+}
+
+- (void) scanAttribute {
+ [self scanAttributeName];
+ [self scanWhitespace];
+ [self scanEquals];
+ [self scanWhitespace];
+ [self scanAttributeValue];
+ [self scanComma];
+ [self scanWhitespace];
+}
+
+- (void) scanAttributeName {
+ NSCharacterSet *letters = [NSCharacterSet letterCharacterSet];
+ NSMutableString *attrName = [[[NSMutableString alloc] init] autorelease];
+
+ // Read at least a single 'letter'.
+ unichar c = [self getch];
+ if (![letters characterIsMember:c])
+ [self rejectWithReason:@"bad character in attribute name"];
+ [attrName appendString:[NSString stringWithCharacters:&c length:1]];
+ while (1) {
+ unichar c = [self getch];
+ if (![letters characterIsMember:c]) {
+ [self putch:c];
+ [_pairs addObject:attrName];
+ return;
+ } else {
+ [attrName appendString:[NSString stringWithCharacters:&c length:1]];
+ }
+ }
+}
+
+- (void) scanWhitespace {
+ NSCharacterSet *whiteSpace = [NSCharacterSet whitespaceCharacterSet];
+
+ // Scan at least a single whitespace character.
+ unichar c = [self getch];
+ if (![whiteSpace characterIsMember:c])
+ [self rejectWithReason:@"expected at least 1 whitespace character"];
+ while (1) {
+ unichar c = [self getch];
+ if (![whiteSpace characterIsMember:c]) {
+ [self putch:c];
+ return;
+ }
+ }
+}
+
+- (void) scanCharater:(NSString *)str {
+ unichar matchChar = [str characterAtIndex:0];
+ unichar c = [self getch];
+ if (c != matchChar) {
+ [self rejectWithReason:[NSString stringWithFormat:@"expected `%C'", matchChar]];
+ }
+}
+
+- (void) scanEquals {
+ [self scanCharater:@"="];
+}
+
+- (void) scanComma {
+ [self scanCharater:@","];
+}
+
+- (void) scanAttributeValue {
+ NSMutableCharacterSet *allAllowedChars = [[NSMutableCharacterSet alloc] init];
+ [allAllowedChars formUnionWithCharacterSet:[NSCharacterSet alphanumericCharacterSet]];
+ [allAllowedChars formUnionWithCharacterSet:[NSCharacterSet whitespaceCharacterSet]];
+ [allAllowedChars formUnionWithCharacterSet:[NSCharacterSet symbolCharacterSet]];
+ [allAllowedChars formUnionWithCharacterSet:[NSCharacterSet punctuationCharacterSet]];
+ [allAllowedChars autorelease];
+
+ NSMutableCharacterSet *charsOutsideQuotes = [allAllowedChars mutableCopy];
+ [charsOutsideQuotes removeCharactersInString:@","];
+ [charsOutsideQuotes autorelease];
+
+ NSString *doubleQuote = @"\"";
+ unichar quoteChar = [doubleQuote characterAtIndex:0];
+
+ NSMutableString *attrValue = [[[NSMutableString alloc] init] autorelease];
+
+ unichar c = [self getch];
+ if (c == quoteChar) {
+ [self putch:c];
+ NSString *quotedString = [self scanQuotedStringWithCharactersFromSet:allAllowedChars];
+ [attrValue appendString:quotedString];
+ } else if (![charsOutsideQuotes characterIsMember:c]) {
+ [self rejectWithReason:@"unexpected character outside of quotes"];
+ } else {
+ [attrValue appendString:[NSString stringWithCharacters:&c length:1]];
+ }
+
+ while (1) {
+ unichar c = [self getch];
+ if (c == quoteChar) {
+ [self putch:c];
+ NSString *quotedString = [self scanQuotedStringWithCharactersFromSet:allAllowedChars];
+ [attrValue appendString:quotedString];
+ } else if (![charsOutsideQuotes characterIsMember:c]) {
+ [_pairs addObject:attrValue];
+ [self putch:c];
+ return;
+ } else {
+ [attrValue appendString:[NSString stringWithCharacters:&c length:1]];
+ }
+ }
+}
+
+- (NSString *) scanQuotedStringWithCharactersFromSet:(NSCharacterSet *)charSet {
+ unichar c = [self getch];
+ unichar quoteChar = [@"\"" characterAtIndex:0];
+ unichar backSlashChar = [@"\\" characterAtIndex:0];
+
+ if (c != quoteChar) {
+ [self rejectWithReason:@"expected quoted string to start with `\"'"];
+ }
+
+ NSMutableString *quotedString = [[[NSMutableString alloc] init] autorelease];
+ while (1) {
+ c = [self getch];
+ if (c == quoteChar) {
+ return quotedString;
+ } else if (c == backSlashChar) {
+ c = [self getch];
+ if (c != quoteChar) {
+ [self rejectWithReason:@"only quote-escapes are allowed inside quotes"];
+ }
+ [quotedString appendString:@"\""];
+ } else {
+ [quotedString appendString:[NSString stringWithCharacters:&c length:1]];
+ }
+ }
+}
+
+@end