1 /* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */
3 #include "credential.h"
4 #include "authutilities.h"
6 #include <Security/AuthorizationTagsPriv.h>
11 #include <membership.h>
12 #include <membershipPriv.h>
14 struct _credential_s
{
15 __AUTH_BASE_STRUCT_HEADER__
;
17 bool right
; // is least-privileged credential
23 CFAbsoluteTime creationTime
;
27 CFMutableSetRef cachedGroups
;
31 _credential_finalize(CFTypeRef value
)
33 credential_t cred
= (credential_t
)value
;
35 free_safe(cred
->name
);
36 free_safe(cred
->realName
);
37 CFReleaseNull(cred
->cachedGroups
);
41 _credential_copy_description(CFTypeRef value
)
43 credential_t cred
= (credential_t
)value
;
44 CFStringRef str
= NULL
;
45 CFTimeZoneRef sys_tz
= CFTimeZoneCopySystem();
46 CFGregorianDate date
= CFAbsoluteTimeGetGregorianDate(cred
->creationTime
, sys_tz
);
47 CFReleaseSafe(sys_tz
);
49 str
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("credential: right=%s, shared=%i, creation=%01i:%01i:%01i, valid=%i"), cred
->name
, cred
->shared
, date
.hour
,date
.minute
,(int32_t)date
.second
, cred
->valid
);
51 str
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("credential: uid=%i, name=%s, shared=%i, creation=%01i:%01i:%01i valid=%i"), cred
->uid
, cred
->name
, cred
->shared
, date
.hour
,date
.minute
,(int32_t)date
.second
, cred
->valid
);
57 _credential_hash(CFTypeRef value
)
59 credential_t cred
= (credential_t
)value
;
60 uint64_t crc
= crc64_init();
62 crc
= crc64_update(crc
, cred
->name
, strlen(cred
->name
));
64 crc
= crc64_update(crc
, &cred
->uid
, sizeof(cred
->uid
));
66 crc
= crc64_update(crc
, &cred
->shared
, sizeof(cred
->shared
));
67 crc
= crc64_final(crc
);
69 return (CFHashCode
)crc
;
73 _credential_equal(CFTypeRef value1
, CFTypeRef value2
)
75 credential_t cred1
= (credential_t
)value1
;
76 credential_t cred2
= (credential_t
)value2
;
78 return _credential_hash(cred1
) == _credential_hash(cred2
);
81 AUTH_TYPE_INSTANCE(credential
,
84 .finalize
= _credential_finalize
,
85 .equal
= _credential_equal
,
86 .hash
= _credential_hash
,
87 .copyFormattingDesc
= NULL
,
88 .copyDebugDesc
= _credential_copy_description
91 static CFTypeID
credential_get_type_id() {
92 static CFTypeID type_id
= _kCFRuntimeNotATypeID
;
93 static dispatch_once_t onceToken
;
95 dispatch_once(&onceToken
, ^{
96 type_id
= _CFRuntimeRegisterClass(&_auth_type_credential
);
105 credential_t cred
= NULL
;
107 cred
= (credential_t
)_CFRuntimeCreateInstance(kCFAllocatorDefault
, credential_get_type_id(), AUTH_CLASS_SIZE(credential
), NULL
);
108 require(cred
!= NULL
, done
);
110 cred
->creationTime
= CFAbsoluteTimeGetCurrent();
111 cred
->cachedGroups
= CFSetCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeSetCallBacks
);;
118 credential_create(uid_t uid
)
120 credential_t cred
= NULL
;
122 cred
= _credential_create();
123 require(cred
!= NULL
, done
);
125 struct passwd
*pw
= getpwuid(uid
);
127 // avoid hinting a locked account
128 // LibInfo started to return asterisk for system accounts in <rdar://problem/31633690> J93: 17a240: Hang during boot (opendirectoryd/powerd deadlock)
129 // so do not make this check for those system accounts
130 if ( (uid
< 500) || (pw
->pw_passwd
== NULL
) || strcmp(pw
->pw_passwd
, "*") ) {
131 cred
->uid
= pw
->pw_uid
;
132 cred
->name
= _copy_string(pw
->pw_name
);
133 cred
->realName
= _copy_string(pw
->pw_gecos
);
136 cred
->uid
= (uid_t
)-2;
147 credential_create_lwos(auth_items_t context
, bool session
)
149 credential_t cred
= NULL
;
151 cred
= _credential_create();
152 require(cred
!= NULL
, done
);
154 const char *username
= session
? "system session" : auth_items_get_string(context
, AGENT_USERNAME
);
155 cred
->uid
= session
? 0 : -500;
156 cred
->name
= _copy_string(username
);
157 cred
->realName
= _copy_string(username
);
164 credential_create_with_credential(credential_t srcCred
, bool shared
)
166 credential_t cred
= NULL
;
168 cred
= _credential_create();
169 require(cred
!= NULL
, done
);
171 cred
->uid
= srcCred
->uid
;
172 cred
->name
= _copy_string(srcCred
->name
);
173 cred
->realName
= _copy_string(srcCred
->realName
);
174 cred
->valid
= srcCred
->valid
;
175 cred
->right
= srcCred
->right
;
176 cred
->shared
= shared
;
183 credential_create_with_right(const char * right
)
185 credential_t cred
= NULL
;
187 cred
= _credential_create();
188 require(cred
!= NULL
, done
);
191 cred
->name
= _copy_string(right
);
192 cred
->uid
= (uid_t
)-2;
200 credential_get_uid(credential_t cred
)
206 credential_get_name(credential_t cred
)
212 credential_get_realname(credential_t cred
)
214 return cred
->realName
;
218 credential_get_creation_time(credential_t cred
)
220 return cred
->creationTime
;
224 credential_get_valid(credential_t cred
)
230 credential_get_shared(credential_t cred
)
236 credential_is_right(credential_t cred
)
242 credential_check_membership(credential_t cred
, const char* group
)
247 return false; // cannot succeed in LWOS as we do not have group data
250 CFStringRef cachedGroup
= NULL
;
251 require(group
!= NULL
, done
);
252 require(cred
->uid
!= 0 || cred
->uid
!= (uid_t
)-2, done
);
253 require(cred
->right
!= true, done
);
255 cachedGroup
= CFStringCreateWithCString(kCFAllocatorDefault
, group
, kCFStringEncodingUTF8
);
256 require(cachedGroup
!= NULL
, done
);
258 if (CFSetGetValue(cred
->cachedGroups
, cachedGroup
) != NULL
) {
264 uuid_t group_uuid
, user_uuid
;
265 rc
= mbr_group_name_to_uuid(group
, group_uuid
);
266 require_noerr(rc
, done
);
268 rc
= mbr_uid_to_uuid(cred
->uid
, user_uuid
);
269 require_noerr(rc
, done
);
271 rc
= mbr_check_membership(user_uuid
, group_uuid
, &ismember
);
272 require_noerr(rc
, done
);
277 CFSetSetValue(cred
->cachedGroups
, cachedGroup
);
281 CFReleaseSafe(cachedGroup
);
286 credential_invalidate(credential_t cred
)