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