File: | auth/auth.c |
Location: | line 458, column 7 |
Description: | Branch condition evaluates to a garbage value |
1 | /* Authentication server. | |||
2 | Copyright (C) 1996,97,98,99,2002 Free Software Foundation, Inc. | |||
3 | Written by Roland McGrath. | |||
4 | ||||
5 | This file is part of the GNU Hurd. | |||
6 | ||||
7 | The GNU Hurd is free software; you can redistribute it and/or | |||
8 | modify it under the terms of the GNU General Public License as | |||
9 | published by the Free Software Foundation; either version 2, or (at | |||
10 | your option) any later version. | |||
11 | ||||
12 | The GNU Hurd is distributed in the hope that it will be useful, but | |||
13 | WITHOUT ANY WARRANTY; without even the implied warranty of | |||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
15 | General Public License for more details. | |||
16 | ||||
17 | You should have received a copy of the GNU General Public License | |||
18 | along with this program; if not, write to the Free Software | |||
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |||
20 | ||||
21 | #include <stddef.h> | |||
22 | #include <stdlib.h> | |||
23 | #include <string.h> | |||
24 | #include <mach.h> | |||
25 | #include <pthread.h> | |||
26 | #include <hurd.h> | |||
27 | #include <hurd/startup.h> | |||
28 | #include <hurd/ports.h> | |||
29 | #include <hurd/ihash.h> | |||
30 | #include <idvec.h> | |||
31 | #include <assert.h> | |||
32 | #include <argp.h> | |||
33 | #include <error.h> | |||
34 | #include <version.h> | |||
35 | #include "auth_S.h" | |||
36 | #include "auth_reply_U.h" | |||
37 | ||||
38 | const char *argp_program_version = STANDARD_HURD_VERSION(auth)"auth" " (GNU Hurd) " "0.5"; | |||
39 | ||||
40 | ||||
41 | /* Auth handles are server ports with sets of ids. */ | |||
42 | struct authhandle | |||
43 | { | |||
44 | struct port_info pi; | |||
45 | struct idvec euids, egids, auids, agids; | |||
46 | }; | |||
47 | ||||
48 | struct port_bucket *auth_bucket; | |||
49 | struct port_class *authhandle_portclass; | |||
50 | ||||
51 | ||||
52 | /* Create a new auth port. */ | |||
53 | ||||
54 | static error_t | |||
55 | create_authhandle (struct authhandle **new) | |||
56 | { | |||
57 | error_t err = ports_create_port (authhandle_portclass, auth_bucket, | |||
58 | sizeof **new, new); | |||
59 | if (! err) | |||
60 | bzero (&(*new)->euids, (void *) &(*new)[1] - (void *) &(*new)->euids); | |||
61 | return err; | |||
62 | } | |||
63 | ||||
64 | /* Clean up a dead auth port. */ | |||
65 | ||||
66 | static void | |||
67 | destroy_authhandle (void *p) | |||
68 | { | |||
69 | struct authhandle *h = p; | |||
70 | idvec_free_contents (&h->euids); | |||
71 | idvec_free_contents (&h->egids); | |||
72 | idvec_free_contents (&h->auids); | |||
73 | idvec_free_contents (&h->agids); | |||
74 | } | |||
75 | ||||
76 | /* Called by server stub functions. */ | |||
77 | ||||
78 | authhandle_t | |||
79 | auth_port_to_handle (auth_t auth) | |||
80 | { | |||
81 | return ports_lookup_port (auth_bucket, auth, authhandle_portclass); | |||
82 | } | |||
83 | ||||
84 | /* id management. */ | |||
85 | ||||
86 | static inline void | |||
87 | idvec_copyout (struct idvec *idvec, uid_t **ids, size_t *nids) | |||
88 | { | |||
89 | if (idvec->num > *nids) | |||
90 | *ids = idvec->ids; | |||
91 | else | |||
92 | memcpy (*ids, idvec->ids, idvec->num * sizeof *ids); | |||
93 | *nids = idvec->num; | |||
94 | } | |||
95 | ||||
96 | #define C(auth, ids)idvec_copyout (&auth->ids, ids, nids) idvec_copyout (&auth->ids, ids, n##ids) | |||
97 | #define OUTIDS(auth)(idvec_copyout (&auth->euids, euids, neuids), idvec_copyout (&auth->egids, egids, negids), idvec_copyout (&auth ->auids, auids, nauids), idvec_copyout (&auth->agids , agids, nagids)) (C (auth, euids)idvec_copyout (&auth->euids, euids, neuids), C (auth, egids)idvec_copyout (&auth->egids, egids, negids), \ | |||
98 | C (auth, auids)idvec_copyout (&auth->auids, auids, nauids), C (auth, agids)idvec_copyout (&auth->agids, agids, nagids)) | |||
99 | ||||
100 | /* Implement auth_getids as described in <hurd/auth.defs>. */ | |||
101 | kern_return_t | |||
102 | S_auth_getids (struct authhandle *auth, | |||
103 | uid_t **euids, | |||
104 | size_t *neuids, | |||
105 | uid_t **auids, | |||
106 | size_t *nauids, | |||
107 | uid_t **egids, | |||
108 | size_t *negids, | |||
109 | uid_t **agids, | |||
110 | size_t *nagids) | |||
111 | { | |||
112 | if (! auth) | |||
113 | return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff)); | |||
114 | ||||
115 | OUTIDS (auth)(idvec_copyout (&auth->euids, euids, neuids), idvec_copyout (&auth->egids, egids, negids), idvec_copyout (&auth ->auids, auids, nauids), idvec_copyout (&auth->agids , agids, nagids)); | |||
116 | ||||
117 | return 0; | |||
118 | } | |||
119 | ||||
120 | /* Implement auth_makeauth as described in <hurd/auth.defs>. */ | |||
121 | kern_return_t | |||
122 | S_auth_makeauth (struct authhandle *auth, | |||
123 | mach_port_t *authpts, size_t nauths, | |||
124 | uid_t *euids, size_t neuids, | |||
125 | uid_t *auids, size_t nauids, | |||
126 | uid_t *egids, size_t negids, | |||
127 | uid_t *agids, size_t nagids, | |||
128 | mach_port_t *newhandle) | |||
129 | { | |||
130 | struct authhandle *newauth, *auths[1 + nauths]; | |||
131 | int hasroot = 0; | |||
132 | error_t err; | |||
133 | size_t i, j; | |||
134 | ||||
135 | if (!auth) | |||
136 | return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff)); | |||
137 | ||||
138 | auths[0] = auth; | |||
139 | ||||
140 | /* Fetch the auth structures for all the ports passed in. */ | |||
141 | for (i = 0; i < nauths; i++) | |||
142 | auths[i + 1] = auth_port_to_handle (authpts[i]); | |||
143 | ||||
144 | ++nauths; | |||
145 | ||||
146 | /* Verify that the union of the handles passed in either contains euid 0 | |||
147 | (root), or contains all the requested ids. */ | |||
148 | ||||
149 | #define isuid(uid, auth)(idvec_contains (&(auth)->euids, uid) || idvec_contains (&(auth)->auids, uid)) \ | |||
150 | (idvec_contains (&(auth)->euids, uid) \ | |||
151 | || idvec_contains (&(auth)->auids, uid)) | |||
152 | #define groupmember(gid, auth)(idvec_contains (&(auth)->egids, gid) || idvec_contains (&(auth)->agids, gid)) \ | |||
153 | (idvec_contains (&(auth)->egids, gid) \ | |||
154 | || idvec_contains (&(auth)->agids, gid)) | |||
155 | #define isroot(auth)(idvec_contains (&(auth)->euids, 0) || idvec_contains ( &(auth)->auids, 0)) isuid (0, auth)(idvec_contains (&(auth)->euids, 0) || idvec_contains ( &(auth)->auids, 0)) | |||
156 | ||||
157 | for (i = 0; i < nauths; i++) | |||
158 | if (auths[i] && isroot (auths[i])(idvec_contains (&(auths[i])->euids, 0) || idvec_contains (&(auths[i])->auids, 0))) | |||
159 | { | |||
160 | hasroot = 1; | |||
161 | break; | |||
162 | } | |||
163 | ||||
164 | if (!hasroot) | |||
165 | { | |||
166 | int has_it; | |||
167 | ||||
168 | for (i = 0; i < neuids; i++) | |||
169 | { | |||
170 | has_it = 0; | |||
171 | for (j = 0; j < nauths; j++) | |||
172 | if (auths[j] && isuid (euids[i], auths[j])(idvec_contains (&(auths[j])->euids, euids[i]) || idvec_contains (&(auths[j])->auids, euids[i]))) | |||
173 | { | |||
174 | has_it = 1; | |||
175 | break; | |||
176 | } | |||
177 | if (!has_it) | |||
178 | goto eperm; | |||
179 | } | |||
180 | ||||
181 | for (i = 0; i < nauids; i++) | |||
182 | { | |||
183 | has_it = 0; | |||
184 | for (j = 0; j < nauths; j++) | |||
185 | if (auths[j] && isuid (auids[i], auths[j])(idvec_contains (&(auths[j])->euids, auids[i]) || idvec_contains (&(auths[j])->auids, auids[i]))) | |||
186 | { | |||
187 | has_it = 1; | |||
188 | break; | |||
189 | } | |||
190 | if (!has_it) | |||
191 | goto eperm; | |||
192 | } | |||
193 | ||||
194 | for (i = 0; i < negids; i++) | |||
195 | { | |||
196 | has_it = 0; | |||
197 | for (j = 0; j < nauths; j++) | |||
198 | if (auths[j] && groupmember (egids[i], auths[j])(idvec_contains (&(auths[j])->egids, egids[i]) || idvec_contains (&(auths[j])->agids, egids[i]))) | |||
199 | { | |||
200 | has_it = 1; | |||
201 | break; | |||
202 | } | |||
203 | if (!has_it) | |||
204 | goto eperm; | |||
205 | } | |||
206 | ||||
207 | for (i = 0; i < nagids; i++) | |||
208 | { | |||
209 | has_it = 0; | |||
210 | for (j = 0; j < nauths; j++) | |||
211 | if (auths[j] && groupmember (agids[i], auths[j])(idvec_contains (&(auths[j])->egids, agids[i]) || idvec_contains (&(auths[j])->agids, agids[i]))) | |||
212 | { | |||
213 | has_it = 1; | |||
214 | break; | |||
215 | } | |||
216 | if (!has_it) | |||
217 | goto eperm; | |||
218 | } | |||
219 | } | |||
220 | ||||
221 | err = create_authhandle (&newauth); | |||
222 | ||||
223 | /* Create a new handle with the specified ids. */ | |||
224 | ||||
225 | #define MERGES (euids); S (egids); S (auids); S (agids); S (euids); S (egids); S (auids); S (agids); | |||
226 | #define S(uids) if (!err) err = idvec_merge_ids (&newauth->uids, uids, n##uids) | |||
227 | ||||
228 | MERGES (euids); S (egids); S (auids); S (agids);; | |||
229 | ||||
230 | #undef S | |||
231 | ||||
232 | if (! err) | |||
233 | { | |||
234 | for (j = 1; j < nauths; ++j) | |||
235 | mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), authpts[j - 1]); | |||
236 | *newhandle = ports_get_right (newauth); | |||
237 | ports_port_deref (newauth); | |||
238 | } | |||
239 | ||||
240 | for (j = 1; j < nauths; j++) | |||
241 | if (auths[j]) | |||
242 | ports_port_deref (auths[j]); | |||
243 | return err; | |||
244 | ||||
245 | eperm: | |||
246 | for (j = 1; j < nauths; j++) | |||
247 | if (auths[j]) | |||
248 | ports_port_deref (auths[j]); | |||
249 | return EPERM((0x10 << 26) | ((1) & 0x3fff)); | |||
250 | } | |||
251 | ||||
252 | /* Transaction handling. */ | |||
253 | ||||
254 | /* Since the user is responsible for freeing the rendezvous port, it has to | |||
255 | * wait for the server to have finished transmitting uids. | |||
256 | * | |||
257 | * The server thus waits for the user to give it uids (unless it was already | |||
258 | * there), transmits them and provides the passthrough port. | |||
259 | * | |||
260 | * The user gives the uids and waits for the passthrough port from the server. | |||
261 | * | |||
262 | * If the user is early, it has to tell the server it arrived. | |||
263 | */ | |||
264 | ||||
265 | /* A pending user. */ | |||
266 | struct pending_user | |||
267 | { | |||
268 | hurd_ihash_locp_t locp; /* Position in the pending_users ihash table. */ | |||
269 | pthread_cond_t wakeup; /* The reader is blocked on this condition. */ | |||
270 | ||||
271 | /* The user's auth handle. */ | |||
272 | struct authhandle *user; | |||
273 | ||||
274 | /* The port to pass back to the user. */ | |||
275 | mach_port_t passthrough; | |||
276 | }; | |||
277 | ||||
278 | /* A pending server. */ | |||
279 | struct pending_server | |||
280 | { | |||
281 | hurd_ihash_locp_t locp; /* Position in the pending_servers ihash table. */ | |||
282 | pthread_cond_t wakeup; /* The server is blocked on this condition. */ | |||
283 | }; | |||
284 | ||||
285 | /* Table of pending transactions keyed on RENDEZVOUS. */ | |||
286 | struct hurd_ihash pending_users | |||
287 | = HURD_IHASH_INITIALIZER (offsetof (struct pending_user, locp)){ .nr_items = 0, .size = 0, .cleanup = (hurd_ihash_cleanup_t) 0, .max_load = 80, .locp_offset = (__builtin_offsetof(struct pending_user, locp))}; | |||
288 | struct hurd_ihash pending_servers | |||
289 | = HURD_IHASH_INITIALIZER (offsetof (struct pending_server, locp)){ .nr_items = 0, .size = 0, .cleanup = (hurd_ihash_cleanup_t) 0, .max_load = 80, .locp_offset = (__builtin_offsetof(struct pending_server, locp))}; | |||
290 | pthread_mutex_t pending_lock = PTHREAD_MUTEX_INITIALIZER{ ((__pthread_spinlock_t) 0), ((__pthread_spinlock_t) 0), 0, 0 , 0, 0, 0, 0 }; | |||
291 | ||||
292 | /* Implement auth_user_authenticate as described in <hurd/auth.defs>. */ | |||
293 | kern_return_t | |||
294 | S_auth_user_authenticate (struct authhandle *userauth, | |||
295 | mach_port_t reply, | |||
296 | mach_msg_type_name_t reply_type, | |||
297 | mach_port_t rendezvous, | |||
298 | mach_port_t *newport, | |||
299 | mach_msg_type_name_t *newporttype) | |||
300 | { | |||
301 | struct pending_server *s; | |||
302 | struct pending_user u; | |||
303 | error_t err; | |||
304 | ||||
305 | if (! userauth) | |||
306 | return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff)); | |||
307 | ||||
308 | if (rendezvous == MACH_PORT_NULL((mach_port_t) 0) || rendezvous == MACH_PORT_DEAD((mach_port_t) ~0)) | |||
309 | return EINVAL((0x10 << 26) | ((22) & 0x3fff)); | |||
310 | ||||
311 | u.user = userauth; | |||
312 | pthread_cond_init (&u.wakeup, NULL((void*)0)); | |||
313 | ||||
314 | pthread_mutex_lock (&pending_lock); | |||
315 | ||||
316 | err = hurd_ihash_add (&pending_users, rendezvous, &u); | |||
317 | if (err) { | |||
318 | pthread_mutex_unlock (&pending_lock); | |||
319 | return err; | |||
320 | } | |||
321 | ||||
322 | /* Give the server the auth port. | |||
323 | We need to add a ref in case the port dies. */ | |||
324 | ports_port_ref (userauth); | |||
325 | ||||
326 | /* Look for this rendezvous in the server list. */ | |||
327 | s = hurd_ihash_find (&pending_servers, rendezvous); | |||
328 | if (s) { | |||
329 | /* Found it! */ | |||
330 | ||||
331 | /* Remove it from the pending list. */ | |||
332 | hurd_ihash_locp_remove (&pending_servers, s->locp); | |||
333 | ||||
334 | /* Tell it we eventually arrived. */ | |||
335 | pthread_cond_signal (&s->wakeup); | |||
336 | } | |||
337 | ||||
338 | ports_interrupt_self_on_port_death (userauth, rendezvous)ports_interrupt_self_on_notification (userauth, rendezvous, ( 0100 + 010)); | |||
339 | /* Wait for server answer. */ | |||
340 | if (pthread_hurd_cond_wait_np (&u.wakeup, &pending_lock) && | |||
341 | hurd_ihash_find (&pending_users, rendezvous)) | |||
342 | /* We were interrupted; remove our record. */ | |||
343 | { | |||
344 | hurd_ihash_locp_remove (&pending_users, u.locp); | |||
345 | ||||
346 | /* Was it a normal interruption or did RENDEZVOUS die? */ | |||
347 | mach_port_type_t type; | |||
348 | mach_port_type (mach_task_self ()((__mach_task_self_ + 0)), rendezvous, &type); | |||
349 | err = type & MACH_PORT_TYPE_DEAD_NAME((mach_port_type_t)(1 << ((((mach_port_right_t) 4))+16) )) ? EINVAL((0x10 << 26) | ((22) & 0x3fff)) : EINTR((0x10 << 26) | ((4) & 0x3fff)); | |||
350 | } | |||
351 | ||||
352 | pthread_mutex_unlock (&pending_lock); | |||
353 | ||||
354 | if (! err) | |||
355 | { | |||
356 | /* Extract the port. */ | |||
357 | *newport = u.passthrough; | |||
358 | *newporttype = MACH_MSG_TYPE_MOVE_SEND17; | |||
359 | mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), rendezvous); | |||
360 | } | |||
361 | ||||
362 | return err; | |||
363 | } | |||
364 | ||||
365 | /* Implement auth_server_authenticate as described in <hurd/auth.defs>. */ | |||
366 | kern_return_t | |||
367 | S_auth_server_authenticate (struct authhandle *serverauth, | |||
368 | mach_port_t reply, | |||
369 | mach_msg_type_name_t reply_type, | |||
370 | mach_port_t rendezvous, | |||
371 | mach_port_t newport, | |||
372 | mach_msg_type_name_t newport_type, | |||
373 | uid_t **euids, | |||
374 | size_t *neuids, | |||
375 | uid_t **auids, | |||
376 | size_t *nauids, | |||
377 | uid_t **egids, | |||
378 | size_t *negids, | |||
379 | uid_t **agids, | |||
380 | size_t *nagids) | |||
381 | { | |||
382 | struct pending_user *u; | |||
383 | struct authhandle *user; | |||
384 | error_t err; | |||
| ||||
385 | ||||
386 | if (! serverauth) | |||
387 | return EOPNOTSUPP((0x10 << 26) | ((45) & 0x3fff)); | |||
388 | ||||
389 | if (rendezvous == MACH_PORT_NULL((mach_port_t) 0) || rendezvous == MACH_PORT_DEAD((mach_port_t) ~0)) | |||
390 | return EINVAL((0x10 << 26) | ((22) & 0x3fff)); | |||
391 | ||||
392 | pthread_mutex_lock (&pending_lock); | |||
393 | ||||
394 | /* Look for this rendezvous in the user list. */ | |||
395 | u = hurd_ihash_find (&pending_users, rendezvous); | |||
396 | if (! u) | |||
397 | { | |||
398 | /* User not here yet, have to wait for it. */ | |||
399 | struct pending_server s; | |||
400 | pthread_cond_init (&s.wakeup, NULL((void*)0)); | |||
401 | err = hurd_ihash_add (&pending_servers, rendezvous, &s); | |||
402 | if (! err) | |||
403 | { | |||
404 | ports_interrupt_self_on_port_death (serverauth, rendezvous)ports_interrupt_self_on_notification (serverauth, rendezvous, (0100 + 010)); | |||
405 | if (pthread_hurd_cond_wait_np (&s.wakeup, &pending_lock) && | |||
406 | hurd_ihash_find (&pending_servers, rendezvous)) | |||
407 | /* We were interrupted; remove our record. */ | |||
408 | { | |||
409 | hurd_ihash_locp_remove (&pending_servers, s.locp); | |||
410 | ||||
411 | /* Was it a normal interruption or did RENDEZVOUS die? */ | |||
412 | mach_port_type_t type; | |||
413 | mach_port_type (mach_task_self ()((__mach_task_self_ + 0)), rendezvous, &type); | |||
414 | err = type & MACH_PORT_TYPE_DEAD_NAME((mach_port_type_t)(1 << ((((mach_port_right_t) 4))+16) )) ? EINVAL((0x10 << 26) | ((22) & 0x3fff)) : EINTR((0x10 << 26) | ((4) & 0x3fff)); | |||
415 | } | |||
416 | else | |||
417 | { | |||
418 | u = hurd_ihash_find (&pending_users, rendezvous); | |||
419 | if (! u) | |||
420 | /* User still not here, odd! */ | |||
421 | err = EINTR((0x10 << 26) | ((4) & 0x3fff)); | |||
422 | } | |||
423 | } | |||
424 | } | |||
425 | ||||
426 | if (u) | |||
427 | { | |||
428 | error_t err2; | |||
429 | ||||
430 | /* Remove it from the pending list. */ | |||
431 | hurd_ihash_locp_remove (&pending_users, u->locp); | |||
432 | ||||
433 | /* Found it! */ | |||
434 | user = u->user; | |||
435 | ||||
436 | pthread_mutex_unlock (&pending_lock); | |||
437 | ||||
438 | /* Tell third party. */ | |||
439 | err2 = auth_server_authenticate_reply (reply, reply_type, 0, | |||
440 | user->euids.ids, user->euids.num, | |||
441 | user->auids.ids, user->auids.num, | |||
442 | user->egids.ids, user->egids.num, | |||
443 | user->agids.ids, user->agids.num); | |||
444 | ||||
445 | if (err2) | |||
446 | mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), reply); | |||
447 | ||||
448 | pthread_mutex_lock (&pending_lock); | |||
449 | ||||
450 | /* Give the user the new port and wake the RPC up. */ | |||
451 | u->passthrough = newport; | |||
452 | ||||
453 | pthread_cond_signal (&u->wakeup); | |||
454 | } | |||
455 | ||||
456 | pthread_mutex_unlock (&pending_lock); | |||
457 | ||||
458 | if (err) | |||
| ||||
459 | return err; | |||
460 | ||||
461 | ports_port_deref (user); | |||
462 | mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), rendezvous); | |||
463 | return MIG_NO_REPLY-305; | |||
464 | } | |||
465 | ||||
466 | ||||
467 | ||||
468 | static int | |||
469 | auth_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp) | |||
470 | { | |||
471 | extern int auth_server (mach_msg_header_t *inp, mach_msg_header_t *outp); | |||
472 | return (auth_server (inp, outp) || | |||
473 | ports_interrupt_server (inp, outp) || | |||
474 | ports_notify_server (inp, outp)); | |||
475 | } | |||
476 | ||||
477 | ||||
478 | int | |||
479 | main (int argc, char **argv) | |||
480 | { | |||
481 | error_t err; | |||
482 | mach_port_t boot; | |||
483 | process_t proc; | |||
484 | mach_port_t hostpriv, masterdev; | |||
485 | struct authhandle *firstauth; | |||
486 | struct argp argp = { 0, 0, 0, "Hurd standard authentication server." }; | |||
487 | ||||
488 | argp_parse (&argp, argc, argv, 0, 0, 0); | |||
489 | ||||
490 | auth_bucket = ports_create_bucket (); | |||
491 | authhandle_portclass = ports_create_class (&destroy_authhandle, 0); | |||
492 | ||||
493 | /* Create the initial root auth handle. */ | |||
494 | err = create_authhandle (&firstauth); | |||
495 | assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "auth.c", 495, __PRETTY_FUNCTION__)); | |||
496 | idvec_add (&firstauth->euids, 0); | |||
497 | idvec_add (&firstauth->auids, 0); | |||
498 | idvec_add (&firstauth->auids, 0); | |||
499 | idvec_merge (&firstauth->egids, &firstauth->euids); | |||
500 | idvec_merge (&firstauth->agids, &firstauth->auids); | |||
501 | ||||
502 | /* Fetch our bootstrap port and contact the bootstrap filesystem. */ | |||
503 | err = task_get_bootstrap_port (mach_task_self (), &boot)(task_get_special_port((((__mach_task_self_ + 0))), 4, (& boot))); | |||
504 | assert_perror (err)(!(err) ? (void) (0) : __assert_perror_fail ((err), "auth.c", 504, __PRETTY_FUNCTION__)); | |||
505 | if (boot == MACH_PORT_NULL((mach_port_t) 0)) | |||
506 | error (2, 0, "auth server can only be run by init during boot"); | |||
507 | err = startup_authinit (boot, ports_get_right (firstauth), | |||
508 | MACH_MSG_TYPE_MAKE_SEND20, &proc); | |||
509 | if (err) | |||
510 | error (2, err, "cannot contact init for bootstrap"); | |||
511 | ||||
512 | /* Register ourselves with the proc server and then start signals. */ | |||
513 | proc_getprivports (proc, &hostpriv, &masterdev); | |||
514 | proc_register_version (proc, hostpriv, "auth", "", HURD_VERSION"0.5"); | |||
515 | mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), masterdev); | |||
516 | _hurd_port_set (&_hurd_ports[INIT_PORT_PROC], proc); | |||
517 | _hurd_proc_init (argv, NULL((void*)0), 0); | |||
518 | ||||
519 | /* Init knows intimately that we will be ready for messages | |||
520 | as soon as this returns. */ | |||
521 | startup_essential_task (boot, mach_task_self ()((__mach_task_self_ + 0)), MACH_PORT_NULL((mach_port_t) 0), "auth", | |||
522 | hostpriv); | |||
523 | mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), boot); | |||
524 | mach_port_deallocate (mach_task_self ()((__mach_task_self_ + 0)), hostpriv); | |||
525 | ||||
526 | /* Be a server. */ | |||
527 | while (1) | |||
528 | ports_manage_port_operations_multithread (auth_bucket, | |||
529 | auth_demuxer, | |||
530 | 30 * 1000, 0, 0); | |||
531 | } |