1/*
2 * Copyright (c) 2014 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#include "application.h"
25
26#include <libproc.h>
27#include <CoreFoundation/CFBundlePriv.h>
28#include <Security/Security.h>
29
30dispatch_queue_t __ApplicationGetQueue( void )
31{
32    static dispatch_once_t once;
33    static dispatch_queue_t queue;
34
35    dispatch_once( &once, ^
36    {
37        queue = dispatch_queue_create( 0, 0 );
38    } );
39
40    return queue;
41}
42
43CFBundleRef _ApplicationCopyBundle( pid_t processID )
44{
45    __block CFBundleRef bundle = 0;
46
47    dispatch_sync( __ApplicationGetQueue( ), ^
48    {
49        int length;
50        uint8_t path[ PROC_PIDPATHINFO_MAXSIZE ];
51
52        length = proc_pidpath( processID, path, PROC_PIDPATHINFO_MAXSIZE );
53
54        if ( length )
55        {
56            CFURLRef url;
57
58            url = CFURLCreateFromFileSystemRepresentation( kCFAllocatorDefault, path, length, TRUE );
59
60            if ( url )
61            {
62                bundle = _CFBundleCreateWithExecutableURLIfMightBeBundle( kCFAllocatorDefault, url );
63
64                CFRelease( url );
65            }
66        }
67    } );
68
69    return bundle;
70}
71
72CFStringRef _ApplicationCopyIdentifier( pid_t processID )
73{
74    __block CFStringRef identifier = 0;
75
76    dispatch_sync( __ApplicationGetQueue( ), ^
77    {
78        CFMutableDictionaryRef attributes;
79
80        attributes = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks );
81
82        if ( attributes )
83        {
84            CFNumberRef number;
85
86            number = CFNumberCreate( kCFAllocatorDefault, kCFNumberIntType, &processID );
87
88            if ( number )
89            {
90                SecCodeRef code = 0;
91
92                CFDictionarySetValue( attributes, kSecGuestAttributePid, number );
93
94                SecCodeCopyGuestWithAttributes( 0, attributes, kSecCSDefaultFlags, &code );
95
96                if ( code )
97                {
98                    CFDictionaryRef information = 0;
99
100                    SecCodeCopySigningInformation( code, kSecCSDefaultFlags, &information );
101
102                    if ( information )
103                    {
104                        identifier = CFDictionaryGetValue( information, kSecCodeInfoIdentifier );
105
106                        if ( identifier )
107                        {
108                            CFRetain( identifier );
109                        }
110
111                        CFRelease( information );
112                    }
113
114                    CFRelease( code );
115                }
116
117                CFRelease( number );
118            }
119
120            CFRelease( attributes );
121        }
122    } );
123
124    return identifier;
125}
126