Вопрос по macos – SMJobBless возвращая ошибку 4098

4

Я пытаюсь установить безопасный вспомогательный инструмент с SMJobBless. Когда происходит сбой и перед вызовом SMJobBless, я вызываю SMJobRemove, потому что мне нужно удалить более старую версию инструмента, и это успешно. SMJobBless возвращает код ошибки 4098. Объект NSError только сообщает мне, что «операция не может быть завершена». Произошла ошибка в подсистеме CodeSigning. & Quot;

Если я перезапущу свой код, функция SMJobBless сработает. Я бы предположил, что это потому, что он был удален ранее, но почему это не сработало в первый раз? Затем я могу общаться с инструментом, и все работает нормально. Наблюдая за тем, что все работает нормально, я уверен, что могу выполнить пять требований для SMJobBless, как описано в документации.

Если я увеличу версию своего инструмента и попытаюсь снова, SMJobRemove будет работать, но, опять же, SMJobBless с кодом ошибки 4098.

Если это имеет значение, я использую OS X 10.7.3.

Ваш Ответ

1   ответ
4

CFBundleCopyInfoDictionaryForURL на вспомогательном инструменте с подписанным кодом?

Если это так, кажется, что эта функция нарушает действительность подписи кода. (Предположительно, потому чтоCFBundle изменяет данные Info.plist в памяти, но это только мое предположение.)

Решением является использованиеSecCodeCopySigningInformation чтобы прочитать информацию о версии вспомогательного инструмента:

-(NSString *) bundleVersionForCodeSignedItemAtURL:(NSURL *)url {
    OSStatus status;

    // Sanity check -- nothing begets nothing
    if (!url) {
        return nil;
    }

    // Get the binary's static code
    SecStaticCodeRef codeRef;
    status = SecStaticCodeCreateWithPath((CFURLRef)url, kSecCSDefaultFlags, &codeRef);
    if (status != noErr) {
        NSLog(@"SecStatucCodeCreateWithPath() error for %@: %d", url, status);
        return nil;
    }

    // Get the code signature info
    CFDictionaryRef codeInfo;
    status = SecCodeCopySigningInformation(codeRef, kSecCSDefaultFlags, &codeInfo);
    if (status != noErr) {
        NSLog(@"SecCodeCopySigningInformation() error for %@: %d", url, status);
        CFRelease(codeRef);
        return nil;
    }

    // The code signature info gives us the Info.plist that was signed, and
    // from there we can retrieve the version
    NSDictionary *bundleInfo = (NSDictionary *) CFDictionaryGetValue(codeInfo, kSecCodeInfoPList);
    NSString *version = [bundleInfo objectForKey:@"CFBundleVersion"];

    // We have ownership of the code signature info, so we must release it.
    // Before we do that, we need to hold onto the version otherwise we go
    // crashing and burning.
    [[version retain] autorelease];
    CFRelease(codeInfo);
    CFRelease(codeRef);

    return version;
}

Чтобы отдать должное, где это необходимо: жизненно важная информация оCFBundleCopyInfoDictionaryForURL пришли из Яна МаклеодаSMJobKit.

Этот код передает файловый дескриптор вспомогательному инструменту.codeRef должно бытьCFRelease()d по возвращении. Я попытался отредактировать сообщение самостоятельно, но оно было отклонено как "слишком незначительная" проблема. LCC
Спасибо @LCC, я только что обновил код. Philipp
Вау! Это была именно та проблема, которая у меня была, и это прекрасно исправило ее. Спасибо за указатель и, что еще лучше, за реальный рабочий код! Я только желаю, чтобы документация Apple для SMJobBless и друзей была лучше. Tim Ruddick

Похожие вопросы