| 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 | } |