1 /*
2 * protocol dispatcher
3 */
4 /*
5
6 Copyright 1990, 1991, 1998 The Open Group
7
8 Permission to use, copy, modify, distribute, and sell this software and its
9 documentation for any purpose is hereby granted without fee, provided that
10 the above copyright notice appear in all copies and that both that
11 copyright notice and this permission notice appear in supporting
12 documentation.
13
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24 Except as contained in this notice, the name of The Open Group shall not be
25 used in advertising or otherwise to promote the sale, use or other dealings
26 in this Software without prior written authorization from The Open Group.
27
28 * Copyright 1990, 1991 Network Computing Devices;
29 * Portions Copyright 1987 by Digital Equipment Corporation
30 *
31 * Permission to use, copy, modify, distribute, and sell this software and
32 * its documentation for any purpose is hereby granted without fee, provided
33 * that the above copyright notice appear in all copies and that both that
34 * copyright notice and this permission notice appear in supporting
35 * documentation, and that the names of Network Computing Devices, or Digital
36 * not be used in advertising or publicity pertaining to distribution
37 * of the software without specific, written prior permission.
38 *
39 * NETWORK COMPUTING DEVICES, AND DIGITAL DISCLAIM ALL WARRANTIES WITH
40 * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
41 * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES,
42 * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
43 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
44 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
45 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
46 * THIS SOFTWARE.
47 */
48
49 #include "config.h"
50
51 #include <stdlib.h>
52 #include "dispatch.h"
53 #include "swapreq.h"
54 #include "swaprep.h"
55
56 #include <X11/fonts/FS.h>
57 #include <X11/fonts/FSproto.h>
58 #include "clientstr.h"
59 #include "authstr.h"
60 #include "osstruct.h"
61 #include "extentst.h"
62 #include "globals.h"
63 #include "fsresource.h"
64 #include "difsfnst.h"
65 #include <X11/fonts/fontstruct.h>
66 #include "site.h"
67 #include "fsevents.h"
68 #include "globals.h"
69 #include "difs.h"
70 #include "access.h"
71
72 static void kill_all_clients(void);
73
74 volatile char dispatchException = 0;
75 volatile char isItTimeToYield;
76
77 ClientPtr currentClient;
78
79 static int nClients = 0;
80 static int nextFreeClientID;
81
82 #define MAJOROP ((fsReq *)client->requestBuffer)->reqType
83
84 #define ALL_FORMAT_BITS (BitmapFormatByteOrderMask | \
85 BitmapFormatBitOrderMask | \
86 BitmapFormatScanlineUnitMask | \
87 BitmapFormatScanlinePadMask | \
88 BitmapFormatImageRectMask)
89
90 #define ALL_FORMAT_MASK_BITS (BitmapFormatMaskByte | \
91 BitmapFormatMaskBit | \
92 BitmapFormatMaskImageRectangle | \
93 BitmapFormatMaskScanLinePad | \
94 BitmapFormatMaskScanLineUnit)
95
96 void
Dispatch(void)97 Dispatch(void)
98 {
99 int nready,
100 result;
101 int *clientReady;
102 ClientPtr client;
103 int op;
104
105 nextFreeClientID = MINCLIENT;
106 nClients = 0;
107
108 clientReady = (int *) ALLOCATE_LOCAL(sizeof(int) * MaxClients);
109 if (!clientReady)
110 return;
111
112 while (1) {
113 /* wait for something */
114 nready = WaitForSomething(clientReady);
115
116 while (!dispatchException && (--nready >= 0)) {
117 client = currentClient = clients[clientReady[nready]];
118
119 /* Client can be NULL if CloseDownClient() is called during
120 this dispatchException loop. */
121 if (client == (ClientPtr)NULL) continue;
122
123 isItTimeToYield = FALSE;
124
125 while (!isItTimeToYield) {
126 result = ReadRequest(client);
127 if (result <= 0) {
128 if (result < 0)
129 CloseDownClient(client);
130 break;
131 }
132 client->sequence++;
133
134 if (result > (MAX_REQUEST_SIZE << 2))
135 result = FSBadLength;
136 else
137 {
138 op = MAJOROP;
139 if (op >= NUM_PROC_VECTORS)
140 result = ProcBadRequest (client);
141 else if (*client->requestVector[op] != NULL)
142 result = (*client->requestVector[op]) (client);
143 else
144 result = FSBadRequest;
145 }
146 if (result != FSSuccess) {
147 if (client->noClientException != FSSuccess)
148 CloseDownClient(client);
149 break;
150 }
151 }
152 FlushAllOutput ();
153 }
154 /* reset if server is a drone and has run out of clients */
155 if (drone_server && nClients == 0) {
156 dispatchException |= DE_RESET;
157 }
158 if (dispatchException) {
159 /* re-read the config file */
160 if (dispatchException & DE_RECONFIG) {
161 NoticeF("re-reading config file\n");
162 if (ReadConfigFile(configfilename) != FSSuccess)
163 ErrorF("couldn't parse config file\n");
164 SetConfigValues();
165 dispatchException &= ~DE_RECONFIG;
166 }
167 /* flush all the caches */
168 if (dispatchException & DE_FLUSH) {
169 NoticeF("flushing all caches\n");
170 dispatchException &= ~DE_FLUSH;
171 }
172 /* reset */
173 if (dispatchException & DE_RESET) {
174 NoticeF("resetting\n");
175 break;
176 }
177 /* die *now* */
178 if (dispatchException & DE_TERMINATE) {
179 NoticeF("terminating\n");
180 kill_all_clients();
181 CloseSockets();
182 CloseErrors();
183 exit(0);
184 break;
185 }
186 }
187 }
188 kill_all_clients();
189 dispatchException = 0;
190 }
191
192 int
ProcInitialConnection(ClientPtr client)193 ProcInitialConnection(ClientPtr client)
194 {
195 REQUEST(fsFakeReq);
196 fsConnClientPrefix *prefix;
197 int whichbyte = 1;
198
199 prefix = (fsConnClientPrefix *) stuff+1;
200 if ((prefix->byteOrder != 'l') && (prefix->byteOrder != 'B'))
201 return (client->noClientException = -2);
202 if (((*(char *) &whichbyte) && (prefix->byteOrder == 'B')) ||
203 (!(*(char *) &whichbyte) && (prefix->byteOrder == 'l'))) {
204 int status;
205
206 client->swapped = TRUE;
207 status = SwapConnClientPrefix(client, prefix);
208 if (status != FSSuccess)
209 return (status);
210 }
211 client->major_version = prefix->major_version;
212 client->minor_version = prefix->minor_version;
213 stuff->reqType = 2;
214 stuff->length += prefix->auth_len;
215 if (client->swapped) {
216 stuff->length = lswaps(stuff->length);
217 }
218 ResetCurrentRequest(client);
219 return client->noClientException;
220 }
221
222 int
ProcEstablishConnection(ClientPtr client)223 ProcEstablishConnection(ClientPtr client)
224 {
225 fsConnClientPrefix *prefix;
226 int ret;
227 pointer auth_data;
228 char *ad;
229 char *server_auth_data;
230 AuthPtr client_auth;
231 int i,
232 num_alts,
233 altlen,
234 auth_accept,
235 auth_index,
236 auth_len;
237 AlternateServerPtr altservers;
238
239 REQUEST(fsFakeReq);
240
241 prefix = (fsConnClientPrefix *) stuff+1;
242 auth_data = prefix + sz_fsConnClientPrefix;
243 client_auth = (AuthPtr) ALLOCATE_LOCAL(prefix->num_auths * sizeof(AuthRec));
244 if (!client_auth) {
245 SendErrToClient(client, FSBadAlloc, (pointer) 0);
246 return FSBadAlloc;
247 }
248 /* XXXX -- this needs work for multiple auth replies */
249
250 /* build up a list of the stuff */
251 for (i = 0, ad = auth_data; i < (int)prefix->num_auths; i++) {
252 if (ad - (char *)auth_data > (stuff->length << 2) - 4) {
253 int lengthword = stuff->length;
254
255 SendErrToClient(client, FSBadLength, (pointer)&lengthword);
256 DEALLOCATE_LOCAL(client_auth);
257 return (FSBadLength);
258 }
259 /* copy carefully in case wire data is not aligned */
260 client_auth[i].namelen = (((unsigned char *)ad)[0] << 8) +
261 ((unsigned char *)ad)[1];
262 ad += 2;
263 client_auth[i].datalen = (((unsigned char *)ad)[0] << 8) +
264 ((unsigned char *)ad)[1];
265 ad += 2;
266 client_auth[i].name = (char *) ad;
267 ad += client_auth[i].namelen;
268 client_auth[i].data = (char *) ad;
269 ad += client_auth[i].datalen;
270 }
271 if (!(int)prefix->num_auths)
272 ad += 4;
273 if (ad - (char *)auth_data > (stuff->length << 2)) {
274 int lengthword = stuff->length;
275
276 SendErrToClient(client, FSBadLength, (pointer)&lengthword);
277 DEALLOCATE_LOCAL(client_auth);
278 return (FSBadLength);
279 }
280
281 num_alts = ListAlternateServers(&altservers);
282 for (i = 0, altlen = 0; i < num_alts; i++) {
283 /* subset + len + namelen + pad */
284 altlen += (2 + altservers[i].namelen + 3) >> 2;
285 }
286
287 auth_index = prefix->num_auths;
288 client->auth_generation = 0;
289 ret = CheckClientAuthorization(client, client_auth,
290 &auth_accept, &auth_index, &auth_len, &server_auth_data);
291 if (auth_index > 0)
292 {
293 AuthContextPtr authp;
294 authp = (AuthContextPtr) fsalloc(sizeof(AuthContextRec));
295 if (!authp) {
296 SendErrToClient(client, FSBadAlloc, (pointer) 0);
297 DEALLOCATE_LOCAL(client_auth);
298 return FSBadAlloc;
299 }
300 authp->authname =
301 (char *) fsalloc(client_auth[auth_index - 1].namelen + 1);
302 authp->authdata =
303 (char *) fsalloc(client_auth[auth_index - 1].datalen + 1);
304 if (!authp->authname || !authp->authdata) {
305 fsfree((char *) authp->authname);
306 fsfree((char *) authp->authdata);
307 fsfree((char *) authp);
308 SendErrToClient(client, FSBadAlloc, (pointer) 0);
309 DEALLOCATE_LOCAL(client_auth);
310 return FSBadAlloc;
311 }
312 memmove( authp->authname, client_auth[auth_index - 1].name,
313 client_auth[auth_index - 1].namelen);
314 memmove( authp->authdata, client_auth[auth_index - 1].data,
315 client_auth[auth_index - 1].datalen);
316 /* Save it with a zero resource id... subsequent
317 SetAuthorizations of None will find it. And it will be freed
318 by FreeClientResources when the connection closes. */
319 if (!AddResource(client->index, 0, RT_AUTHCONT,(pointer) authp))
320 {
321 fsfree((char *) authp->authname);
322 fsfree((char *) authp->authdata);
323 fsfree((char *) authp);
324 SendErrToClient(client, FSBadAlloc, (pointer) 0);
325 DEALLOCATE_LOCAL(client_auth);
326 return FSBadAlloc;
327 }
328 client->auth = client->default_auth = authp;
329 }
330 else
331 client->auth = client->default_auth = (AuthContextPtr)0;
332
333 DEALLOCATE_LOCAL(client_auth);
334
335 if (ret != FSSuccess) {
336 SendErrToClient(client, FSBadAlloc, (pointer) 0);
337 return FSBadAlloc;
338 }
339 else {
340 fsConnSetup csp = {
341 .status = auth_accept,
342 /* we implement backwards compatibility for version 1.0 */
343 .major_version = (client->major_version == 1) ?
344 client->major_version : FS_PROTOCOL,
345 .minor_version = FS_PROTOCOL_MINOR,
346 .num_alternates = num_alts,
347 .alternate_len = altlen,
348 .auth_len = auth_len >> 2,
349 .auth_index = auth_index
350 };
351 if (client->swapped) {
352 WriteSConnSetup(client, &csp);
353 } else {
354 (void) WriteToClient(client, SIZEOF(fsConnSetup), (char *) &csp);
355 }
356 }
357
358 /* send the alternates info */
359 for (i = 0; i < num_alts; i++) {
360 char tmp[258];
361
362 /* WriteToClient pads, so we have to fake some things */
363 tmp[0] = altservers[i].subset;
364 tmp[1] = altservers[i].namelen;
365 memmove( (char *) &tmp[2], altservers[i].name, altservers[i].namelen);
366 (void) WriteToClient(client, altservers[i].namelen + 2, tmp);
367 }
368
369 if (auth_len)
370 (void) WriteToClient(client, auth_len, (char *) server_auth_data);
371
372 if (auth_accept != AuthSuccess) {
373 nClients--;
374 return (client->noClientException = -2);
375 }
376 client->requestVector = client->swapped ? SwappedProcVector : ProcVector;
377 client->sequence = 0;
378 if (client->swapped)
379 (void) WriteSConnectionInfo(client, ConnInfoLen, ConnectionInfo);
380 else
381 (void) WriteToClient(client, ConnInfoLen, ConnectionInfo);
382
383 #ifdef DEBUG
384 fprintf(stderr, "Establishing new connection\n");
385 #endif
386
387 return client->noClientException;
388 }
389
390 /*
391 * NOTE -- the incoming data may be mangled
392 */
393
394 void
DoSendErrToClient(ClientPtr client,int error,pointer data)395 DoSendErrToClient(
396 ClientPtr client,
397 int error,
398 pointer data) /* resource id, format, resolution, etc */
399 {
400 fsError rep = {
401 .type = FS_Error,
402 .request = error,
403 .sequenceNumber = client->sequence,
404 .timestamp = GetTimeInMillis(),
405 .major_opcode = ((fsReq *) client->requestBuffer)->reqType,
406 .minor_opcode = 0
407 };
408 int extralen = 0;
409
410 switch (error) {
411 case FSBadFormat:
412 extralen = SIZEOF(fsBitmapFormat);
413 break;
414 case FSBadFont:
415 case FSBadAccessContext:
416 case FSBadIDChoice:
417 case FSBadEventMask:
418 if (data) {
419 if (client->swapped)
420 SwapLongs((long *) data, 1);
421 extralen = 4;
422 }
423 break;
424 case FSBadRange:
425 extralen = SIZEOF(fsRange);
426 break;
427 case FSBadResolution:
428 if (data) {
429 if (client->swapped)
430 SwapShorts((short *) data, 1);
431 /* note sneaky hack */
432 rep.pad = *(CARD16 *) data;
433 data = (char *)data + 2;
434 extralen = 4;
435 }
436 break;
437 case FSBadLength:
438 if (data) {
439 if (client->swapped)
440 SwapLongs((long *) data, 1);
441 extralen = 4;
442 }
443 break;
444 default:
445 /* nothing else to send */
446 break;
447 }
448
449 rep.length = (SIZEOF(fsError) + extralen) >> 2;
450
451 WriteErrorToClient(client, &rep);
452
453 if (extralen)
454 WriteToClient(client, extralen, (char *) data);
455 }
456
457 /* ARGSUSED */
458 int
ProcBadRequest(ClientPtr client)459 ProcBadRequest(ClientPtr client)
460 {
461 SendErrToClient(client, FSBadRequest, NULL);
462 return FSBadRequest;
463 }
464
465 int
ProcNoop(ClientPtr client)466 ProcNoop(ClientPtr client)
467 {
468 REQUEST(fsReq);
469 REQUEST_AT_LEAST_SIZE(fsReq);
470
471 return client->noClientException;
472 }
473
474 int
ProcListCatalogues(ClientPtr client)475 ProcListCatalogues(ClientPtr client)
476 {
477 int len,
478 num;
479 char *catalogues;
480 fsListCataloguesReply rep = {
481 .type = FS_Reply,
482 .sequenceNumber = client->sequence,
483 .num_replies = 0
484 };
485
486 REQUEST(fsListCataloguesReq);
487 REQUEST_AT_LEAST_SIZE(fsListCataloguesReq);
488
489 num = ListCatalogues((char *)stuff + SIZEOF(fsListCataloguesReq),
490 stuff->nbytes, stuff->maxNames,
491 &catalogues, &len);
492 rep.num_catalogues = num;
493 rep.length = (SIZEOF(fsListCataloguesReply) + len + 3) >> 2;
494
495 WriteReplyToClient(client, SIZEOF(fsListCataloguesReply), &rep);
496 (void) WriteToClient(client, len, (char *) catalogues);
497 fsfree((char *) catalogues);
498 return client->noClientException;
499 }
500
501 int
ProcSetCatalogues(ClientPtr client)502 ProcSetCatalogues(ClientPtr client)
503 {
504 char *new_cat;
505 int err,
506 len;
507 int num;
508
509 REQUEST(fsSetCataloguesReq);
510 REQUEST_AT_LEAST_SIZE(fsSetCataloguesReq);
511
512 if (stuff->num_catalogues == 0) {
513 /* use the default */
514 num = ListCatalogues("*", 1, 10000, &new_cat, &len);
515 } else {
516 num = stuff->num_catalogues;
517 err = ValidateCatalogues(&num, (char *)stuff + SIZEOF(fsSetCataloguesReq));
518 if (err == FSSuccess) {
519 len = (stuff->length << 2) - SIZEOF(fsSetCataloguesReq);
520 new_cat = (char *) fsalloc(len);
521 if (!new_cat)
522 return FSBadAlloc;
523 memmove( new_cat, (char *)stuff + SIZEOF(fsSetCataloguesReq), len);
524 } else {
525 SendErrToClient(client, err, (pointer) &num);
526 return err;
527 }
528 }
529 if (client->catalogues)
530 fsfree((char *) client->catalogues);
531 client->catalogues = new_cat;
532 client->num_catalogues = num;
533 return client->noClientException;
534 }
535
536 int
ProcGetCatalogues(ClientPtr client)537 ProcGetCatalogues(ClientPtr client)
538 {
539 int len,
540 i,
541 size;
542 char *cp;
543
544 REQUEST(fsGetCataloguesReq);
545 REQUEST_AT_LEAST_SIZE(fsGetCataloguesReq);
546
547 for (i = 0, len = 0, cp = client->catalogues;
548 i < client->num_catalogues; i++) {
549 size = *cp++;
550 len += size + 1; /* str length + size byte */
551 cp += size;
552 }
553
554 {
555 fsGetCataloguesReply rep = {
556 .type = FS_Reply,
557 .num_catalogues = client->num_catalogues,
558 .sequenceNumber = client->sequence,
559 .length = (SIZEOF(fsGetCataloguesReply) + len + 3) >> 2
560 };
561
562 WriteReplyToClient(client, SIZEOF(fsGetCataloguesReply), &rep);
563 }
564 (void) WriteToClient(client, len, client->catalogues);
565
566 return client->noClientException;
567 }
568
569 int
ProcCreateAC(ClientPtr client)570 ProcCreateAC(ClientPtr client)
571 {
572 AuthPtr acp;
573 AuthContextPtr authp;
574 int accept,
575 i,
576 err,
577 index,
578 size;
579 char *ad;
580 char *auth_data;
581
582 REQUEST(fsCreateACReq);
583 REQUEST_AT_LEAST_SIZE(fsCreateACReq);
584
585 authp = (AuthContextPtr) LookupIDByType(client->index, stuff->acid,
586 RT_AUTHCONT);
587 if (authp) {
588 int aligned_acid = stuff->acid;
589 SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_acid);
590 return FSBadIDChoice;
591 }
592 acp = NULL;
593 if (stuff->num_auths)
594 {
595 acp = (AuthPtr) ALLOCATE_LOCAL(stuff->num_auths * sizeof(AuthRec));
596 if (!acp) {
597 SendErrToClient(client, FSBadAlloc, (pointer) NULL);
598 return FSBadAlloc;
599 }
600 }
601 /* build up a list of the stuff */
602 for (i = 0, ad = (char *)stuff + SIZEOF(fsCreateACReq);
603 i < (int)stuff->num_auths; i++) {
604 if (ad - (char *)stuff + SIZEOF(fsCreateACReq) >
605 (stuff->length << 2) - 4) {
606 int lengthword = stuff->length;
607
608 SendErrToClient(client, FSBadLength, (pointer)&lengthword);
609 DEALLOCATE_LOCAL(acp);
610 return (FSBadLength);
611 }
612 /* copy carefully in case data is not aligned */
613 acp[i].namelen = (((unsigned char *)ad)[0] << 8) +
614 ((unsigned char *)ad)[1];
615 ad += 2;
616 acp[i].datalen = (((unsigned char *)ad)[0] << 8) +
617 ((unsigned char *)ad)[1];
618 ad += 2;
619 acp[i].name = (char *) ad;
620 ad += acp[i].namelen;
621 acp[i].data = (char *) ad;
622 ad += acp[i].datalen;
623 }
624 if (ad - (char *)stuff > (stuff->length << 2)) {
625 int lengthword = stuff->length;
626
627 SendErrToClient(client, FSBadLength, (pointer)&lengthword);
628 if (acp)
629 DEALLOCATE_LOCAL(acp);
630 return (FSBadLength);
631 }
632
633 /* XXX needs work for AuthContinue */
634 index = stuff->num_auths;
635 err = CheckClientAuthorization(client, acp, &accept, &index, &size,
636 &auth_data);
637
638 if (err != FSSuccess) {
639 SendErrToClient(client, err, (pointer) 0);
640 if (acp)
641 DEALLOCATE_LOCAL(acp);
642 return err;
643 }
644 authp = (AuthContextPtr) fsalloc(sizeof(AuthContextRec));
645 if (!authp) {
646 goto alloc_failure;
647 }
648 authp->authname = NULL;
649 authp->authdata = NULL;
650 if (index > 0)
651 {
652 authp->authname = (char *) fsalloc(acp[index - 1].namelen + 1);
653 authp->authdata = (char *) fsalloc(acp[index - 1].datalen + 1);
654 if (!authp->authname || !authp->authdata) {
655 fsfree((char *) authp->authname);
656 fsfree((char *) authp->authdata);
657 fsfree((char *) authp);
658 goto alloc_failure;
659 }
660 memmove( authp->authname, acp[index - 1].name, acp[index - 1].namelen);
661 memmove( authp->authdata, acp[index - 1].data, acp[index - 1].datalen);
662 }
663 else
664 size = 0;
665 authp->acid = stuff->acid;
666 if (!AddResource(client->index, stuff->acid, RT_AUTHCONT,(pointer) authp))
667 {
668 alloc_failure:
669 SendErrToClient(client, FSBadAlloc, (pointer) 0);
670 if (acp)
671 DEALLOCATE_LOCAL(acp);
672 return FSBadAlloc;
673 }
674 DEALLOCATE_LOCAL(acp);
675 {
676 fsCreateACReply rep = {
677 .type = FS_Reply,
678 .auth_index = index,
679 .sequenceNumber = client->sequence,
680 .status = accept,
681 .length = (SIZEOF(fsCreateACReply) + size) >> 2
682 };
683
684 WriteReplyToClient(client, SIZEOF(fsCreateACReply), &rep);
685 }
686 if (size)
687 (void) WriteToClient(client, size, auth_data);
688
689 return client->noClientException;
690 }
691
692 /* ARGSUSED */
693 int
DeleteAuthCont(pointer value,FSID id)694 DeleteAuthCont (pointer value, FSID id)
695 {
696 AuthContextPtr authp = (AuthContextPtr) value;
697
698 if (authp->authname)
699 fsfree (authp->authname);
700 if (authp->authdata)
701 fsfree (authp->authdata);
702 fsfree (authp);
703 return 1;
704 }
705
706 int
ProcFreeAC(ClientPtr client)707 ProcFreeAC(ClientPtr client)
708 {
709 AuthContextPtr authp;
710
711 REQUEST(fsFreeACReq);
712 REQUEST_AT_LEAST_SIZE(fsFreeACReq);
713 authp = (AuthContextPtr) LookupIDByType(client->index, stuff->id,
714 RT_AUTHCONT);
715 if (!authp) {
716 int aligned_id = stuff->id;
717 SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_id);
718 return FSBadIDChoice;
719 }
720 if (client->auth == authp)
721 client->auth = client->default_auth;
722 FreeResource(client->index, stuff->id, RT_NONE);
723 return client->noClientException;
724 }
725
726 int
ProcSetAuthorization(ClientPtr client)727 ProcSetAuthorization(ClientPtr client)
728 {
729 AuthContextPtr acp;
730
731 REQUEST(fsSetAuthorizationReq);
732 REQUEST_AT_LEAST_SIZE(fsSetAuthorizationReq);
733 acp = (AuthContextPtr) LookupIDByType(client->index, stuff->id,
734 RT_AUTHCONT);
735 if (!acp) {
736 int aligned_id = stuff->id;
737 SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_id);
738 return FSBadIDChoice;
739 }
740 client->auth = acp; /* XXX does this need a refcount? */
741 return client->noClientException;
742 }
743
744 int
ProcSetResolution(ClientPtr client)745 ProcSetResolution(ClientPtr client)
746 {
747 fsResolution *new_res;
748
749 REQUEST(fsSetResolutionReq);
750 REQUEST_AT_LEAST_SIZE(fsSetResolutionReq);
751
752 if ((stuff->length << 2) - SIZEOF(fsSetResolutionReq) <
753 stuff->num_resolutions * SIZEOF(fsResolution)) {
754 int lengthword = stuff->length;
755
756 SendErrToClient(client, FSBadLength, &lengthword);
757 return FSBadLength;
758 }
759 new_res = (fsResolution *)
760 fsalloc(SIZEOF(fsResolution) * stuff->num_resolutions);
761 if (!new_res) {
762 SendErrToClient(client, FSBadAlloc, NULL);
763 return FSBadAlloc;
764 }
765 fsfree((char *) client->resolutions);
766 memmove( (char *) new_res, (char *)stuff + SIZEOF(fsSetResolutionReq),
767 (stuff->num_resolutions * SIZEOF(fsResolution)));
768 client->resolutions = new_res;
769 client->num_resolutions = stuff->num_resolutions;
770
771 return client->noClientException;
772 }
773
774 int
ProcGetResolution(ClientPtr client)775 ProcGetResolution(ClientPtr client)
776 {
777 REQUEST(fsReq);
778 REQUEST_AT_LEAST_SIZE(fsReq);
779
780 if ((stuff->length << 2) - SIZEOF(fsResolution) < client->num_resolutions *
781 sizeof(fsResolution)) {
782 int lengthword = stuff->length;
783
784 SendErrToClient(client, FSBadLength, &lengthword);
785 return FSBadLength;
786 }
787 else {
788 fsGetResolutionReply reply = {
789 .type = FS_Reply,
790 .num_resolutions = client->num_resolutions,
791 .sequenceNumber = client->sequence,
792 .length = (SIZEOF(fsGetResolutionReply) +
793 client->num_resolutions * SIZEOF(fsResolution)) >> 2
794 };
795
796 WriteReplyToClient(client, SIZEOF(fsGetResolutionReply), &reply);
797 }
798 if (client->swapped)
799 client->pSwapReplyFunc = CopySwap16Write;
800
801 WriteSwappedDataToClient(client,
802 (client->num_resolutions * SIZEOF(fsResolution)), (short *)client->resolutions);
803
804 return client->noClientException;
805 }
806
807 int
ProcListFonts(ClientPtr client)808 ProcListFonts(ClientPtr client)
809 {
810 REQUEST(fsListFontsReq);
811 REQUEST_FIXED_SIZE(fsListFontsReq, stuff->nbytes);
812
813 return ListFonts(client, stuff->nbytes,
814 (unsigned char *)stuff + SIZEOF(fsListFontsReq),
815 stuff->maxNames);
816 }
817
818 int
ProcListFontsWithXInfo(ClientPtr client)819 ProcListFontsWithXInfo(ClientPtr client)
820 {
821 REQUEST(fsListFontsWithXInfoReq);
822 REQUEST_FIXED_SIZE(fsListFontsWithXInfoReq, stuff->nbytes);
823
824 return StartListFontsWithInfo(client, stuff->nbytes,
825 (unsigned char *)stuff + SIZEOF(fsListFontsWithXInfoReq), stuff->maxNames);
826 }
827
828 int
ProcOpenBitmapFont(ClientPtr client)829 ProcOpenBitmapFont(ClientPtr client)
830 {
831 FontPtr pfont;
832 int nbytes,
833 err;
834 unsigned char *fname;
835
836 REQUEST(fsOpenBitmapFontReq);
837 fname = (unsigned char *)stuff + SIZEOF(fsOpenBitmapFontReq);
838 nbytes = *fname++;
839
840 REQUEST_FIXED_SIZE(fsOpenBitmapFontReq, (nbytes + 1));
841
842 pfont = (FontPtr) LookupIDByType(client->index, stuff->fid, RT_FONT);
843 if (pfont) {
844 int aligned_fid = stuff->fid;
845 SendErrToClient(client, FSBadIDChoice, (pointer) &aligned_fid);
846 return FSBadIDChoice;
847 }
848 if (stuff->format_hint != 0 &&
849 stuff->format_hint & ~ALL_FORMAT_BITS) {
850 int aligned_format_hint = stuff->format_hint;
851 SendErrToClient(client, FSBadFormat, (pointer) &aligned_format_hint);
852 return FSBadFormat;
853 }
854 if (stuff->format_mask & ~ALL_FORMAT_MASK_BITS) {
855 int aligned_format_mask = stuff->format_mask;
856 SendErrToClient(client, FSBadFormat, (pointer) &aligned_format_mask);
857 return FSBadFormat;
858 }
859 err = OpenFont(client, stuff->fid, stuff->format_hint, stuff->format_mask,
860 nbytes, (char *) fname);
861
862 if (err == FSSuccess) {
863 return client->noClientException;
864 } else {
865 return err;
866 }
867 }
868
869 int
ProcQueryXInfo(ClientPtr client)870 ProcQueryXInfo(ClientPtr client)
871 {
872 ClientFontPtr cfp;
873 int err,
874 lendata;
875 fsQueryXInfoReply reply = {
876 .type = FS_Reply,
877 .sequenceNumber = client->sequence
878 };
879 fsPropInfo *prop_info;
880
881 REQUEST(fsQueryXInfoReq);
882
883 REQUEST_AT_LEAST_SIZE(fsQueryXInfoReq);
884
885 cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->id, RT_FONT);
886 if (!cfp) {
887 int aligned_id = stuff->id;
888 SendErrToClient(client, FSBadFont, (pointer) &aligned_id);
889 return FSBadFont;
890 }
891
892 /* get the header */
893 fsPack_XFontInfoHeader(&cfp->font->info, &reply, client->major_version);
894 err = convert_props(&cfp->font->info, &prop_info);
895
896 switch (err)
897 {
898 case Successful:
899 break;
900 case AllocError:
901 SendErrToClient(client, FSBadAlloc, (pointer) 0);
902 return err;
903 default:
904 ErrorF("ProcQueryXInfo: unexpected return val %d from convert_props\n",
905 err);
906 SendErrToClient(client, FSBadImplementation, (pointer) 0);
907 return err;
908 }
909 lendata = SIZEOF(fsPropInfo) +
910 prop_info->num_offsets * SIZEOF(fsPropOffset) +
911 prop_info->data_len;
912
913 reply.length = (SIZEOF(fsQueryXInfoReply) + lendata + 3) >> 2;
914 WriteReplyToClient(client, SIZEOF(fsQueryXInfoReply), &reply);
915
916 if (client->swapped)
917 SwapPropInfo(prop_info);
918 (void) WriteToClient(client, lendata, (char *) prop_info);
919
920 fsfree((char *) prop_info);
921 return client->noClientException;
922 }
923
924 int
ProcQueryXExtents(ClientPtr client)925 ProcQueryXExtents(ClientPtr client)
926 {
927 ClientFontPtr cfp;
928 int err;
929 int item_size;
930
931 REQUEST(fsQueryXExtents8Req);
932
933 REQUEST_AT_LEAST_SIZE(fsQueryXExtents8Req);
934
935 cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->fid, RT_FONT);
936 if (!cfp) {
937 int aligned_fid = stuff->fid;
938 SendErrToClient(client, FSBadFont, (pointer) &aligned_fid);
939 return FSBadFont;
940 }
941 item_size = (stuff->reqType == FS_QueryXExtents8) ? 1 : 2;
942
943 if (stuff->num_ranges >
944 ((stuff->length << 2) - SIZEOF(fsQueryXExtents8Req))/item_size) {
945 int num_ranges = stuff->num_ranges;
946 SendErrToClient(client, FSBadLength, (pointer)&num_ranges);
947 return FSBadLength;
948 }
949
950 /* get the extents */
951 err = QueryExtents(client, cfp, item_size,
952 stuff->num_ranges, stuff->range,
953 (char *)stuff + SIZEOF(fsQueryXExtents8Req));
954
955 if (err != FSSuccess) {
956 return err;
957 } else
958 return client->noClientException;
959 }
960
961 int
ProcQueryXBitmaps(ClientPtr client)962 ProcQueryXBitmaps(ClientPtr client)
963 {
964 ClientFontPtr cfp;
965 int err;
966 int item_size;
967
968 REQUEST(fsQueryXBitmaps8Req);
969
970 REQUEST_AT_LEAST_SIZE(fsQueryXBitmaps8Req);
971
972 cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->fid, RT_FONT);
973 if (!cfp) {
974 int aligned_fid = stuff->fid;
975 SendErrToClient(client, FSBadFont, (pointer) &aligned_fid);
976 return FSBadFont;
977 }
978 if (stuff->format & ~ALL_FORMAT_BITS) {
979 int aligned_format = stuff->format;
980 SendErrToClient(client, FSBadFormat, (pointer) &aligned_format);
981 return FSBadFormat;
982 }
983 assert((stuff->reqType == FS_QueryXBitmaps8) || (stuff->reqType == FS_QueryXBitmaps16));
984 item_size = (stuff->reqType == FS_QueryXBitmaps8) ? 1 : 2;
985
986 if (stuff->num_ranges >
987 ((stuff->length << 2) - SIZEOF(fsQueryXBitmaps8Req))/item_size) {
988 int num_ranges = stuff->num_ranges;
989 SendErrToClient(client, FSBadLength, (pointer)&num_ranges);
990 return FSBadLength;
991 }
992 /* get the glyphs */
993 err = QueryBitmaps(client, cfp, item_size, stuff->format,
994 stuff->num_ranges, stuff->range,
995 (char *)stuff + SIZEOF(fsQueryXBitmaps8Req));
996
997 if (err != FSSuccess) {
998 return err;
999 } else {
1000 return client->noClientException;
1001 }
1002 }
1003
1004 int
ProcCloseFont(ClientPtr client)1005 ProcCloseFont(ClientPtr client)
1006 {
1007 ClientFontPtr cfp;
1008
1009 REQUEST(fsResourceReq);
1010
1011 REQUEST_SIZE_MATCH(fsResourceReq);
1012 cfp = (ClientFontPtr) LookupIDByType(client->index, stuff->id, RT_FONT);
1013 if (cfp) {
1014 FreeResource(client->index, stuff->id, RT_NONE);
1015 return client->noClientException;
1016 } else {
1017 int aligned_id = stuff->id;
1018 SendErrToClient(client, FSBadFont, (pointer) &aligned_id);
1019 return FSBadFont;
1020 }
1021 }
1022
1023 void
DoCloseDownClient(ClientPtr client)1024 DoCloseDownClient(ClientPtr client)
1025 {
1026 if (client->clientGone != CLIENT_GONE) {
1027 DeleteClientFontStuff(client);
1028 client->clientGone = CLIENT_GONE;
1029 CloseDownConnection(client);
1030 --nClients;
1031 }
1032
1033 if (ClientIsAsleep(client))
1034 ClientSignal((pointer)client);
1035 else
1036 {
1037 FreeClientResources(client);
1038 if (client->index < nextFreeClientID)
1039 nextFreeClientID = client->index;
1040 clients[client->index] = NullClient;
1041 #ifdef DebugConnectionTranslation
1042 CheckFileNumbers();
1043 #endif /* DebugConnectionTranslation */
1044
1045
1046 if (currentClient == client)
1047 currentClient = serverClient;
1048 fsfree(client);
1049
1050 #ifdef DEBUG
1051 fprintf(stderr, "Shut down client\n");
1052 #endif
1053
1054 while (!clients[currentMaxClients - 1])
1055 currentMaxClients--;
1056 }
1057 }
1058
1059 static void
kill_all_clients(void)1060 kill_all_clients(void)
1061 {
1062 int i;
1063
1064 for (i = MINCLIENT; i < currentMaxClients; i++) {
1065 if (clients[i])
1066 CloseDownClient(clients[i]);
1067 }
1068 }
1069
1070 void
InitProcVectors(void)1071 InitProcVectors(void)
1072 {
1073 int i;
1074
1075 for (i = 0; i < NUM_PROC_VECTORS; i++) {
1076 if (!ProcVector[i]) {
1077 ProcVector[i] = SwappedProcVector[i] = ProcBadRequest;
1078 ReplySwapVector[i] = (ReplySwapFunc)NotImplemented;
1079 }
1080 }
1081 for (i = FSLASTEvent; i < NUM_EVENT_VECTORS; i++) {
1082 EventSwapVector[i] = (EventSwapFunc)NotImplemented;
1083 }
1084 }
1085
1086 void
InitClient(ClientPtr client,int i,pointer ospriv)1087 InitClient(
1088 ClientPtr client,
1089 int i,
1090 pointer ospriv)
1091 {
1092 if (i != SERVER_CLIENT) {
1093 nClients++;
1094 }
1095 client->index = i;
1096 client->sequence = 0;
1097 client->last_request_time = GetTimeInMillis();
1098 client->clientGone = CLIENT_ALIVE;
1099 client->noClientException = FSSuccess;
1100 client->requestVector = InitialVector;
1101 client->osPrivate = ospriv;
1102 client->swapped = FALSE;
1103
1104 client->auth = (AuthContextPtr) 0;
1105 client->catalogues = NULL;
1106 client->num_catalogues = 0;
1107 client->num_resolutions = 0;
1108 client->resolutions = (fsResolution *) 0;
1109 client->eventmask = (Mask) 0;
1110 }
1111
1112 ClientPtr
NextAvailableClient(pointer ospriv)1113 NextAvailableClient(pointer ospriv)
1114 {
1115 int i;
1116 ClientPtr client;
1117 fsFakeReq data;
1118
1119 i = nextFreeClientID;
1120 if (i == MaxClients)
1121 return NullClient;
1122
1123 clients[i] = client = (ClientPtr) fsalloc(sizeof(ClientRec));
1124 if (!client)
1125 return NullClient;
1126
1127 InitClient(client, i, ospriv);
1128
1129 if (!InitClientResources(client)) {
1130 fsfree(client);
1131 return NullClient;
1132 }
1133 data.reqType = 1;
1134 data.length = (sizeof(fsFakeReq) + SIZEOF(fsConnClientPrefix)) >> 2;
1135 if (!InsertFakeRequest(client, (char *) &data, sizeof(fsFakeReq))) {
1136 FreeClientResources(client);
1137 fsfree(client);
1138 return NullClient;
1139 }
1140 if (i == currentMaxClients)
1141 currentMaxClients++;
1142 while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID])
1143 nextFreeClientID++;
1144
1145 /* if we've maxed out, try to clone */
1146 if (nextFreeClientID == MaxClients) {
1147 CloneMyself();
1148 }
1149 return client;
1150 }
1151
1152 void
MarkClientException(ClientPtr client)1153 MarkClientException(ClientPtr client)
1154 {
1155 client->noClientException = -2;
1156 }
1157