]> git.saurik.com Git - apple/libc.git/blob - gen/asl_core.c
Libc-594.1.4.tar.gz
[apple/libc.git] / gen / asl_core.c
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;
60 if (l == 0)
61 {
62 if (s[0] == '\0') return 0;
63 l = strlen(s);
64 }
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 }