1 /* Copyright (c) 2012 Apple Inc. All rights reserved. */
5 #include "authutilities.h"
11 #define MECHANISM_ID "id"
12 #define MECHANISM_PLUGIN "plugin"
13 #define MECHANISM_PARAM "param"
14 #define MECHANISM_PRIVILEGED "privileged"
16 static const char SystemPlugins
[] = "/System/Library/CoreServices/SecurityAgentPlugins";
17 static const char LibraryPlugins
[] = "/Library/Security/SecurityAgentPlugins";
18 static const char BuiltinMechanismPrefix
[] = "builtin";
20 typedef struct _mechTypeItem
26 static mechTypeItem mechTypeMap
[] =
28 { "entitled", kMechanismTypeEntitled
}
32 __AUTH_BASE_STRUCT_HEADER__
;
43 _mechanism_finalize(CFTypeRef value
)
45 mechanism_t mech
= (mechanism_t
)value
;
47 CFReleaseSafe(mech
->data
);
48 free_safe(mech
->string
);
52 _mechanism_equal(CFTypeRef value1
, CFTypeRef value2
)
54 mechanism_t mech1
= (mechanism_t
)value1
;
55 mechanism_t mech2
= (mechanism_t
)value2
;
61 if (!_compare_string(mechanism_get_plugin(mech1
), mechanism_get_plugin(mech2
))) {
65 if (!_compare_string(mechanism_get_param(mech1
), mechanism_get_param(mech2
))) {
69 return mechanism_is_privileged(mech1
) == mechanism_is_privileged(mech2
);
73 _mechanism_copy_description(CFTypeRef value
)
75 mechanism_t mech
= (mechanism_t
)value
;
76 return CFCopyDescription(mech
->data
);
80 _mechanism_hash(CFTypeRef value
)
82 uint64_t crc
= crc64_init();
83 mechanism_t mech
= (mechanism_t
)value
;
85 const char * str
= mechanism_get_plugin(mech
);
86 crc
= crc64_update(crc
, str
, strlen(str
));
87 str
= mechanism_get_plugin(mech
);
88 crc
= crc64_update(crc
, str
, strlen(str
));
89 bool priv
= mechanism_is_privileged(mech
);
90 crc
= crc64_update(crc
, &priv
, sizeof(priv
));
91 crc
= crc64_final(crc
);
96 AUTH_TYPE_INSTANCE(mechanism
,
99 .finalize
= _mechanism_finalize
,
100 .equal
= _mechanism_equal
,
101 .hash
= _mechanism_hash
,
102 .copyFormattingDesc
= NULL
,
103 .copyDebugDesc
= _mechanism_copy_description
106 static CFTypeID
mechanism_get_type_id() {
107 static CFTypeID type_id
= _kCFRuntimeNotATypeID
;
108 static dispatch_once_t onceToken
;
110 dispatch_once(&onceToken
, ^{
111 type_id
= _CFRuntimeRegisterClass(&_auth_type_mechanism
);
120 mechanism_t mech
= (mechanism_t
)_CFRuntimeCreateInstance(kCFAllocatorDefault
, mechanism_get_type_id(), AUTH_CLASS_SIZE(mechanism
), NULL
);
121 require(mech
!= NULL
, done
);
123 mech
->data
= auth_items_create();
129 static void _mechanism_set_type(mechanism_t mech
)
131 const char * plugin
= mechanism_get_plugin(mech
);
132 const char * param
= mechanism_get_param(mech
);
133 if (strncasecmp(plugin
, BuiltinMechanismPrefix
, sizeof(BuiltinMechanismPrefix
)) == 0) {
134 size_t n
= sizeof(mechTypeMap
)/sizeof(mechTypeItem
);
135 for (size_t i
= 0; i
< n
; i
++) {
136 if (strcasecmp(mechTypeMap
[i
].name
, param
) == 0) {
137 mech
->type
= mechTypeMap
[i
].type
;
145 mechanism_create_with_sql(auth_items_t sql
)
147 mechanism_t mech
= NULL
;
148 require(sql
!= NULL
, done
);
149 require(auth_items_get_int64(sql
, MECHANISM_ID
) != 0, done
);
151 mech
= _mechanism_create();
152 require(mech
!= NULL
, done
);
154 auth_items_copy(mech
->data
, sql
);
156 _mechanism_set_type(mech
);
163 mechanism_create_with_string(const char * str
, authdb_connection_t dbconn
)
165 mechanism_t mech
= NULL
;
166 require(str
!= NULL
, done
);
167 require(strchr(str
,':') != NULL
, done
);
169 mech
= _mechanism_create();
170 require(mech
!= NULL
, done
);
172 const char delimiters
[] = ":,";
173 size_t buf_len
= strlen(str
)+1;
174 char * buf
= (char*)calloc(1u, buf_len
);
175 strlcpy(buf
, str
, buf_len
);
177 char * tok
= strtok(buf
, delimiters
);
179 auth_items_set_string(mech
->data
, MECHANISM_PLUGIN
, tok
);
181 tok
= strtok(NULL
, delimiters
);
183 auth_items_set_string(mech
->data
, MECHANISM_PARAM
, tok
);
185 tok
= strtok(NULL
, delimiters
);
187 auth_items_set_int64(mech
->data
, MECHANISM_PRIVILEGED
, strcasecmp("privileged", tok
) == 0);
192 mechanism_sql_fetch(mech
, dbconn
);
195 _mechanism_set_type(mech
);
202 bool _pluginExists(const char * plugin
, const char * base
)
206 require(plugin
!= NULL
, done
);
207 require(base
!= NULL
, done
);
209 char filePath
[PATH_MAX
];
210 char realPath
[PATH_MAX
+1];
211 snprintf(filePath
, sizeof(filePath
), "%s/%s.bundle", base
, plugin
);
213 require(realpath(filePath
, realPath
) != NULL
, done
);
214 require(strncmp(realPath
, base
, strlen(base
)) == 0, done
);
216 if (access(filePath
, F_OK
) == 0) {
225 mechanism_exists(mechanism_t mech
)
231 const char * plugin
= mechanism_get_plugin(mech
);
232 if (plugin
== NULL
) {
236 if (strncasecmp(plugin
, BuiltinMechanismPrefix
, sizeof(BuiltinMechanismPrefix
)) == 0) {
241 if (_pluginExists(plugin
, SystemPlugins
)) {
246 if (_pluginExists(plugin
,LibraryPlugins
)) {
255 mechanism_sql_fetch(mechanism_t mech
, authdb_connection_t dbconn
)
257 __block
bool result
= false;
259 authdb_step(dbconn
, "SELECT id FROM mechanisms WHERE plugin = ? AND param = ? AND privileged = ? LIMIT 1", ^(sqlite3_stmt
* stmt
) {
260 sqlite3_bind_text(stmt
, 1, mechanism_get_plugin(mech
), -1, NULL
);
261 sqlite3_bind_text(stmt
, 2, mechanism_get_param(mech
), -1, NULL
);
262 sqlite3_bind_int(stmt
, 3, mechanism_is_privileged(mech
));
263 }, ^bool(auth_items_t data
) {
265 auth_items_copy(mech
->data
, data
);
273 mechanism_sql_commit(mechanism_t mech
, authdb_connection_t dbconn
)
277 result
= authdb_step(dbconn
, "INSERT INTO mechanisms VALUES (NULL,?,?,?)", ^(sqlite3_stmt
*stmt
) {
278 sqlite3_bind_text(stmt
, 1, mechanism_get_plugin(mech
), -1, NULL
);
279 sqlite3_bind_text(stmt
, 2, mechanism_get_param(mech
), -1, NULL
);
280 sqlite3_bind_int(stmt
, 3, mechanism_is_privileged(mech
));
287 mechanism_get_string(mechanism_t mech
)
290 asprintf(&mech
->string
, "%s:%s%s", mechanism_get_plugin(mech
), mechanism_get_param(mech
), mechanism_is_privileged(mech
) ? ",privileged" : "");
297 mechanism_get_id(mechanism_t mech
)
299 return auth_items_get_int64(mech
->data
, MECHANISM_ID
);
303 mechanism_get_plugin(mechanism_t mech
)
305 return auth_items_get_string(mech
->data
, MECHANISM_PLUGIN
);
309 mechanism_get_param(mechanism_t mech
)
311 return auth_items_get_string(mech
->data
, MECHANISM_PARAM
);
315 mechanism_is_privileged(mechanism_t mech
)
317 return auth_items_get_int64(mech
->data
, MECHANISM_PRIVILEGED
);
321 mechanism_get_type(mechanism_t mech
)