sogo/UI/MailPartViewers/UIxMailPartSignedViewer.m

242 lines
5.5 KiB
Objective-C

/* UIxMailPartSignedViewer.m - this file is part of SOGo
*
* Copyright (C) 2009-2015 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_OPENSSL
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pkcs7.h>
#include <openssl/x509.h>
#endif
#import <Foundation/NSData.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSValue.h>
#import <Mailer/SOGoMailObject.h>
#import "UIxMailRenderingContext.h"
#import "UIxMailPartSignedViewer.h"
@implementation UIxMailPartSignedViewer : UIxMailPartMixedViewer
#ifdef HAVE_OPENSSL
- (BOOL) supportsSMIME
{
return YES;
}
- (X509_STORE *) _setupVerify
{
X509_STORE *store;
X509_LOOKUP *lookup;
BOOL success;
success = NO;
store = X509_STORE_new ();
OpenSSL_add_all_algorithms ();
if (store)
{
lookup = X509_STORE_add_lookup (store, X509_LOOKUP_file());
if (lookup)
{
X509_LOOKUP_load_file (lookup, NULL, X509_FILETYPE_DEFAULT);
lookup = X509_STORE_add_lookup (store, X509_LOOKUP_hash_dir());
if (lookup)
{
X509_LOOKUP_add_dir (lookup, NULL, X509_FILETYPE_DEFAULT);
ERR_clear_error();
success = YES;
}
}
}
if (!success)
{
if (store)
{
X509_STORE_free(store);
store = NULL;
}
}
return store;
}
- (void) _processMessage
{
NSString *issuer, *subject;
NSData *signedData;
STACK_OF(X509) *certs;
X509_STORE *x509Store;
BIO *msgBio, *inData;
char sslError[1024];
PKCS7 *p7;
int err, i;
memset(sslError, 0, 1024);
ERR_clear_error();
signedData = [[self clientObject] content];
msgBio = BIO_new_mem_buf ((void *) [signedData bytes], [signedData length]);
inData = NULL;
p7 = SMIME_read_PKCS7(msgBio, &inData);
subject = nil;
issuer = nil;
certs = NULL;
if (p7)
{
i = OBJ_obj2nid(p7->type);
if (i == NID_pkcs7_signed)
{
X509 *x;
certs=p7->d.sign->cert;
if (sk_X509_num(certs) > 0)
{
BIO *buf;
char p[256];
memset(p, 0, 256);
x = sk_X509_value(certs,0);
buf = BIO_new(BIO_s_mem());
X509_NAME_print_ex(buf, X509_get_subject_name(x), 0, XN_FLAG_ONELINE & ~ASN1_STRFLGS_ESC_MSB);
BIO_gets(buf, p, 256);
subject = [NSString stringWithUTF8String: p];
memset(p, 0, 256);
X509_NAME_print_ex(buf, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE & ~ASN1_STRFLGS_ESC_MSB);
BIO_gets(buf, p, 256);
issuer = [NSString stringWithUTF8String: p];
BIO_free(buf);
}
}
err = ERR_get_error();
if (err)
{
ERR_error_string_n (err, sslError, 1023);
validSignature = NO;
}
else
{
x509Store = [self _setupVerify];
validSignature = (PKCS7_verify(p7, NULL, x509Store, inData,
NULL, PKCS7_DETACHED) == 1);
err = ERR_get_error();
if (err)
ERR_error_string_n(err, sslError, 1023);
if (x509Store)
X509_STORE_free (x509Store);
}
}
BIO_free (msgBio);
if (inData)
BIO_free (inData);
validationMessage = [NSMutableString string];
if (!validSignature)
[validationMessage appendString: [self labelForKey: @"Digital signature is not valid"]];
else
[validationMessage appendString: [self labelForKey: @"Message is signed"]];
if (issuer && subject)
[validationMessage appendFormat: @"\n%@: %@\n%@: %@",
[self labelForKey: @"Subject"], subject,
[self labelForKey: @"Issuer"], issuer];
processed = YES;
}
- (BOOL) validSignature
{
if (!processed)
[self _processMessage];
return validSignature;
}
- (NSString *) validationMessage
{
if (!processed)
[self _processMessage];
return validationMessage;
}
#else
- (BOOL) supportsSMIME
{
return NO;
}
- (BOOL) validSignature
{
return NO;
}
- (NSString *) validationMessage
{
return nil;
}
#endif
- (id) renderedPart {
id info, viewer;
NSArray *parts;
NSMutableArray *renderedParts;
NSUInteger i, max;
parts = [[self bodyInfo] objectForKey: @"parts"];
max = [parts count];
renderedParts = [NSMutableArray arrayWithCapacity: max];
for (i = 0; i < max; i++)
{
[self setChildIndex: i];
[self setChildInfo: [parts objectAtIndex: i]];
info = [self childInfo];
viewer = [[[self context] mailRenderingContext] viewerForBodyInfo:info];
[viewer setBodyInfo: info];
[viewer setPartPath: [self childPartPath]];
[renderedParts addObject: [viewer renderedPart]];
}
return [NSDictionary dictionaryWithObjectsAndKeys:
[self className], @"type",
[NSNumber numberWithBool: [self supportsSMIME]], @"supports-smime",
[NSNumber numberWithBool: [self validSignature]], @"valid",
[self validationMessage], @"error",
renderedParts, @"content",
nil];
}
@end