]>
Commit | Line | Data |
---|---|---|
b5d655f7 A |
1 | /* |
2 | * Copyright (c) 2007 Apple Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * "Portions Copyright (c) 2007 Apple Inc. All Rights | |
7 | * Reserved. This file contains Original Code and/or Modifications of | |
8 | * Original Code as defined in and that are subject to the Apple Public | |
9 | * Source License Version 1.0 (the 'License'). You may not use this file | |
10 | * except in compliance with the License. Please obtain a copy of the | |
11 | * License at http://www.apple.com/publicsource and read it before using | |
12 | * this file. | |
13 | * | |
14 | * The Original Code and all software distributed under the License are | |
15 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
18 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the | |
19 | * License for the specific language governing rights and limitations | |
20 | * under the License." | |
21 | * | |
22 | * @APPLE_LICENSE_HEADER_END@ | |
23 | */ | |
24 | ||
25 | #include <asl_core.h> | |
26 | #include <string.h> | |
27 | #include <membership.h> | |
28 | #include <pthread.h> | |
29 | ||
30 | /* | |
31 | * Message ID generation | |
32 | */ | |
33 | static uint64_t _asl_core_msg_next_id = 1; | |
34 | static pthread_mutex_t msg_id_lock = PTHREAD_MUTEX_INITIALIZER; | |
35 | ||
36 | #define mix(a, b, c) \ | |
37 | { \ | |
38 | a -= b; a -= c; a ^= (c>>13); \ | |
39 | b -= c; b -= a; b ^= (a<< 8); \ | |
40 | c -= a; c -= b; c ^= (b>>13); \ | |
41 | a -= b; a -= c; a ^= (c>>12); \ | |
42 | b -= c; b -= a; b ^= (a<<16); \ | |
43 | c -= a; c -= b; c ^= (b>> 5); \ | |
44 | a -= b; a -= c; a ^= (c>> 3); \ | |
45 | b -= c; b -= a; b ^= (a<<10); \ | |
46 | c -= a; c -= b; c ^= (b>>15); \ | |
47 | } | |
48 | ||
49 | /* | |
50 | * Hash is used to improve string search. | |
51 | */ | |
52 | uint32_t | |
53 | asl_core_string_hash(const char *s, uint32_t inlen) | |
54 | { | |
55 | uint32_t a, b, c, l, len; | |
56 | ||
57 | if (s == NULL) return 0; | |
58 | ||
59 | l = inlen; | |
34e8f829 A |
60 | if (l == 0) |
61 | { | |
62 | if (s[0] == '\0') return 0; | |
63 | l = strlen(s); | |
64 | } | |
b5d655f7 A |
65 | |
66 | len = l; | |
67 | a = b = 0x9e3779b9; | |
68 | c = 0; | |
69 | ||
70 | while (len >= 12) | |
71 | { | |
72 | a += (s[0] + ((uint32_t)s[1]<<8) + ((uint32_t)s[ 2]<<16) + ((uint32_t)s[ 3]<<24)); | |
73 | b += (s[4] + ((uint32_t)s[5]<<8) + ((uint32_t)s[ 6]<<16) + ((uint32_t)s[ 7]<<24)); | |
74 | c += (s[8] + ((uint32_t)s[9]<<8) + ((uint32_t)s[10]<<16) + ((uint32_t)s[11]<<24)); | |
75 | ||
76 | mix(a, b, c); | |
77 | ||
78 | s += 12; | |
79 | len -= 12; | |
80 | } | |
81 | ||
82 | c += l; | |
83 | switch(len) | |
84 | { | |
85 | case 11: c += ((uint32_t)s[10]<<24); | |
86 | case 10: c += ((uint32_t)s[9]<<16); | |
87 | case 9 : c += ((uint32_t)s[8]<<8); | |
88 | ||
89 | case 8 : b += ((uint32_t)s[7]<<24); | |
90 | case 7 : b += ((uint32_t)s[6]<<16); | |
91 | case 6 : b += ((uint32_t)s[5]<<8); | |
92 | case 5 : b += s[4]; | |
93 | ||
94 | case 4 : a += ((uint32_t)s[3]<<24); | |
95 | case 3 : a += ((uint32_t)s[2]<<16); | |
96 | case 2 : a += ((uint32_t)s[1]<<8); | |
97 | case 1 : a += s[0]; | |
98 | } | |
99 | ||
100 | mix(a, b, c); | |
101 | ||
102 | if (c == 0) c = 1; | |
103 | return c; | |
104 | } | |
105 | ||
106 | const char * | |
107 | asl_core_error(uint32_t code) | |
108 | { | |
109 | switch (code) | |
110 | { | |
111 | case ASL_STATUS_OK: return "Operation Succeeded"; | |
112 | case ASL_STATUS_INVALID_ARG: return "Invalid Argument"; | |
113 | case ASL_STATUS_INVALID_STORE: return "Invalid Data Store"; | |
114 | case ASL_STATUS_INVALID_STRING: return "Invalid String"; | |
115 | case ASL_STATUS_INVALID_ID: return "Invalid ID Number"; | |
116 | case ASL_STATUS_INVALID_MESSAGE: return "Invalid Message"; | |
117 | case ASL_STATUS_NOT_FOUND: return "Not Found"; | |
118 | case ASL_STATUS_READ_FAILED: return "Read Operation Failed"; | |
119 | case ASL_STATUS_WRITE_FAILED: return "Write Operation Failed"; | |
120 | case ASL_STATUS_NO_MEMORY: return "System Memory Allocation Failed"; | |
121 | case ASL_STATUS_ACCESS_DENIED: return "Access Denied"; | |
122 | case ASL_STATUS_READ_ONLY: return "Read Only Access"; | |
123 | case ASL_STATUS_WRITE_ONLY: return "Write Only Access"; | |
124 | case ASL_STATUS_MATCH_FAILED: return "Match Failed"; | |
125 | case ASL_STATUS_NO_RECORDS: return "No More Records"; | |
126 | } | |
127 | ||
128 | return "Operation Failed"; | |
129 | } | |
130 | ||
131 | static uint32_t | |
132 | asl_core_check_user_access(int32_t msgu, int32_t readu) | |
133 | { | |
134 | /* -1 means anyone may read */ | |
135 | if (msgu == -1) return ASL_STATUS_OK; | |
136 | ||
137 | /* Check for exact match */ | |
138 | if (msgu == readu) return ASL_STATUS_OK; | |
139 | ||
140 | return ASL_STATUS_ACCESS_DENIED; | |
141 | } | |
142 | ||
143 | static uint32_t | |
144 | asl_core_check_group_access(int32_t msgg, int32_t readu, int32_t readg) | |
145 | { | |
146 | int check; | |
147 | uuid_t uu, gu; | |
148 | ||
149 | /* -1 means anyone may read */ | |
150 | if (msgg == -1) return ASL_STATUS_OK; | |
151 | ||
152 | /* Check for exact match */ | |
153 | if (msgg == readg) return ASL_STATUS_OK; | |
154 | ||
155 | /* Check if user (u) is in read group (msgg) */ | |
156 | mbr_uid_to_uuid(readu, uu); | |
157 | mbr_gid_to_uuid(msgg, gu); | |
158 | ||
159 | check = 0; | |
160 | mbr_check_membership(uu, gu, &check); | |
161 | if (check != 0) return ASL_STATUS_OK; | |
162 | ||
163 | return ASL_STATUS_ACCESS_DENIED; | |
164 | } | |
165 | ||
166 | uint32_t | |
167 | asl_core_check_access(int32_t msgu, int32_t msgg, int32_t readu, int32_t readg, uint16_t flags) | |
168 | { | |
169 | uint16_t uset, gset; | |
170 | ||
171 | /* root (uid 0) may always read */ | |
172 | if (readu == 0) return ASL_STATUS_OK; | |
173 | ||
174 | uset = flags & ASL_MSG_FLAG_READ_UID_SET; | |
175 | gset = flags & ASL_MSG_FLAG_READ_GID_SET; | |
176 | ||
177 | /* if no access controls are set, anyone may read */ | |
178 | if ((uset | gset) == 0) return ASL_STATUS_OK; | |
179 | ||
180 | /* if only uid is set, then access is only by uid match */ | |
181 | if ((uset != 0) && (gset == 0)) return asl_core_check_user_access(msgu, readu); | |
182 | ||
183 | /* if only gid is set, then access is only by gid match */ | |
184 | if ((uset == 0) && (gset != 0)) return asl_core_check_group_access(msgg, readu, readg); | |
185 | ||
186 | /* both uid and gid are set - check user, then group */ | |
187 | if ((asl_core_check_user_access(msgu, readu)) == ASL_STATUS_OK) return ASL_STATUS_OK; | |
188 | return asl_core_check_group_access(msgg, readu, readg); | |
189 | } | |
190 | ||
191 | uint64_t | |
192 | asl_core_htonq(uint64_t n) | |
193 | { | |
194 | #ifdef __BIG_ENDIAN__ | |
195 | return n; | |
196 | #else | |
197 | u_int32_t t; | |
198 | union | |
199 | { | |
200 | u_int64_t q; | |
201 | u_int32_t l[2]; | |
202 | } x; | |
203 | ||
204 | x.q = n; | |
205 | t = x.l[0]; | |
206 | x.l[0] = htonl(x.l[1]); | |
207 | x.l[1] = htonl(t); | |
208 | ||
209 | return x.q; | |
210 | #endif | |
211 | } | |
212 | ||
213 | uint64_t | |
214 | asl_core_ntohq(uint64_t n) | |
215 | { | |
216 | #ifdef __BIG_ENDIAN__ | |
217 | return n; | |
218 | #else | |
219 | u_int32_t t; | |
220 | union | |
221 | { | |
222 | u_int64_t q; | |
223 | u_int32_t l[2]; | |
224 | } x; | |
225 | ||
226 | x.q = n; | |
227 | t = x.l[0]; | |
228 | x.l[0] = ntohl(x.l[1]); | |
229 | x.l[1] = ntohl(t); | |
230 | ||
231 | return x.q; | |
232 | #endif | |
233 | } | |
234 | ||
235 | uint64_t | |
236 | asl_core_new_msg_id(uint64_t start) | |
237 | { | |
238 | uint64_t out; | |
239 | ||
240 | pthread_mutex_lock(&msg_id_lock); | |
241 | ||
242 | if (start != 0) _asl_core_msg_next_id = start; | |
243 | ||
244 | out = _asl_core_msg_next_id; | |
245 | _asl_core_msg_next_id++; | |
246 | ||
247 | pthread_mutex_unlock(&msg_id_lock); | |
248 | ||
249 | return out; | |
250 | } |