int XdmcpReadHeader (XdmcpBufferPtr buffer, XdmcpHeaderPtr header) { if (XdmcpReadCARD16 (buffer, &header->version) && XdmcpReadCARD16 (buffer, &header->opcode) && XdmcpReadCARD16 (buffer, &header->length)) return TRUE; return FALSE; }
static void send_alive(struct sockaddr *from, int fromlen, int length, int fd) { CARD32 sessionID; CARD16 displayNumber; struct display *d; XdmcpHeader header; CARD8 sendRunning; CARD32 sendSessionID; Debug("send <alive>\n"); if(XdmcpReadCARD16(&buffer, &displayNumber) && XdmcpReadCARD32(&buffer, &sessionID)) { if(length == 6) { if(!(d = FindDisplayBySessionID(sessionID))) d = FindDisplayByAddress((XdmcpNetaddr)from, fromlen, displayNumber); sendRunning = 0; sendSessionID = 0; if(d && d->status == running) { if(d->sessionID == sessionID) sendRunning = 1; sendSessionID = d->sessionID; } header.version = XDM_PROTOCOL_VERSION; header.opcode = (CARD16)ALIVE; header.length = 5; Debug("<alive>: %d %ld\n", sendRunning, (long)sendSessionID); XdmcpWriteHeader(&buffer, &header); XdmcpWriteCARD8(&buffer, sendRunning); XdmcpWriteCARD32(&buffer, sendSessionID); XdmcpFlush(fd, &buffer, (XdmcpNetaddr)from, fromlen); } } }
int XdmcpReadARRAY16 (XdmcpBufferPtr buffer, ARRAY16Ptr array) { int i; /* * When returning FALSE, guarantee that array->data = 0. * This allows the user to safely call XdmcpDisposeARRAY16(array) * regardless of the return value below. * Note that XdmcpDisposeARRAY*(array) will call free(array->data), * so we must guarantee that array->data is NULL or a malloced pointer. */ if (!XdmcpReadCARD8 (buffer, &array->length)) { array->data = NULL; return FALSE; } if (!array->length) { array->data = NULL; return TRUE; } array->data = (CARD16 *) malloc(array->length * sizeof (CARD16)); if (!array->data) return FALSE; for (i = 0; i < (int)array->length; i++) { if (!XdmcpReadCARD16 (buffer, &array->data[i])) { free(array->data); array->data = NULL; array->length = 0; return FALSE; } } return TRUE; }
static void manage(struct sockaddr *from, int fromlen, int length, int fd) { CARD32 sessionID; CARD16 displayNumber; ARRAY8 displayClass; int expectlen; struct protoDisplay *pdpy; struct display *d; char *name = NULL; char *class2 = NULL; XdmcpNetaddr from_save; ARRAY8 clientAddress, clientPort; CARD16 connectionType; Debug("<manage> %d\n", length); displayClass.data = 0; displayClass.length = 0; if(XdmcpReadCARD32(&buffer, &sessionID) && XdmcpReadCARD16(&buffer, &displayNumber) && XdmcpReadARRAY8(&buffer, &displayClass)) { expectlen = 4 + /* session ID */ 2 + /* displayNumber */ 2 + displayClass.length; /* displayClass */ if(expectlen != length) { Debug("<manage> length error got %d expect %d\n", length, expectlen); goto abort; } pdpy = FindProtoDisplay((XdmcpNetaddr)from, fromlen, displayNumber); Debug("<manage> session ID %ld, pdpy %p\n", (long)sessionID, pdpy); if(!pdpy || pdpy->sessionID != sessionID) { /* * We may have already started a session for this display * but it hasn't seen the response in the form of an * XOpenDisplay() yet. So check if it is in the list of active * displays, and if so check that the session id's match. * If all this is true, then we have a duplicate request that * can be ignored. */ if(!pdpy && (d = FindDisplayByAddress((XdmcpNetaddr)from, fromlen, displayNumber)) && d->sessionID == sessionID) { Debug("manage: got duplicate pkt, ignoring\n"); goto abort; } Debug("session ID %ld refused\n", (long)sessionID); if(pdpy) Debug("existing session ID %ld\n", (long)pdpy->sessionID); send_refuse(from, fromlen, sessionID, fd); } else { name = NetworkAddressToName(pdpy->connectionType, &pdpy->connectionAddress, from, pdpy->displayNumber); if(!name) { Debug("could not compute display name\n"); send_failed(from, fromlen, "(no name)", sessionID, "out of memory", fd); goto abort; } Debug("computed display name: %s\n", name); if((d = FindDisplayByName(name))) { Debug("terminating active session for %s\n", d->name); StopDisplay(d); } if(displayClass.length) { if(!StrNDup(&class2, (char *)displayClass.data, displayClass.length)) { send_failed(from, fromlen, name, sessionID, "out of memory", fd); goto abort; } } if(!(from_save = (XdmcpNetaddr)Malloc(fromlen))) { send_failed(from, fromlen, name, sessionID, "out of memory", fd); goto abort; } memmove(from_save, from, fromlen); if(!(d = NewDisplay(name))) { free((char *)from_save); send_failed(from, fromlen, name, sessionID, "out of memory", fd); goto abort; } d->class2 = class2; class2 = 0; d->displayType = dForeign | dTransient | dFromXDMCP; d->sessionID = pdpy->sessionID; d->from.data = (unsigned char *)from_save; d->from.length = fromlen; d->displayNumber = pdpy->displayNumber; ClientAddress(from, &clientAddress, &clientPort, &connectionType); d->useChooser = 0; d->xdmcpFd = fd; if(IsIndirectClient(&clientAddress, connectionType)) { Debug("IsIndirectClient\n"); ForgetIndirectClient(&clientAddress, connectionType); if(UseChooser(&clientAddress, connectionType)) { d->useChooser = 1; Debug("use chooser for %s\n", d->name); } } d->clientAddr = clientAddress; d->connectionType = connectionType; d->remoteHost = NetworkAddressToHostname(pdpy->connectionType, &pdpy->connectionAddress); XdmcpDisposeARRAY8(&clientPort); if(pdpy->fileAuthorization) { d->authorizations = (Xauth **)Malloc(sizeof(Xauth *)); if(!d->authorizations) { free((char *)from_save); free((char *)d); send_failed(from, fromlen, name, sessionID, "out of memory", fd); goto abort; } d->authorizations[0] = pdpy->fileAuthorization; d->authNum = 1; pdpy->fileAuthorization = 0; } DisposeProtoDisplay(pdpy); Debug("starting display %s,%s\n", d->name, d->class2); if(LoadDisplayResources(d) < 0) { LogError( "Unable to read configuration for display %s; " "stopping it.\n", d->name); StopDisplay(d); } else StartDisplay(d); CloseGetter(); } } abort: XdmcpDisposeARRAY8(&displayClass); if(name) free((char *)name); if(class2) free((char *)class2); }
static void request_respond(struct sockaddr *from, int fromlen, int length, int fd) { CARD16 displayNumber; ARRAY16 connectionTypes; ARRAYofARRAY8 connectionAddresses; ARRAY8 authenticationName; ARRAY8 authenticationData; ARRAYofARRAY8 authorizationNames; ARRAY8 manufacturerDisplayID; ARRAY8Ptr reason = 0; int expectlen; int i, j; struct protoDisplay *pdpy; ARRAY8 authorizationName, authorizationData; ARRAY8Ptr connectionAddress; Debug("<request> respond %d\n", length); connectionTypes.data = 0; connectionAddresses.data = 0; authenticationName.data = 0; authenticationData.data = 0; authorizationNames.data = 0; authorizationName.length = 0; authorizationData.length = 0; manufacturerDisplayID.data = 0; if(XdmcpReadCARD16(&buffer, &displayNumber) && XdmcpReadARRAY16(&buffer, &connectionTypes) && XdmcpReadARRAYofARRAY8(&buffer, &connectionAddresses) && XdmcpReadARRAY8(&buffer, &authenticationName) && XdmcpReadARRAY8(&buffer, &authenticationData) && XdmcpReadARRAYofARRAY8(&buffer, &authorizationNames) && XdmcpReadARRAY8(&buffer, &manufacturerDisplayID)) { expectlen = 0; expectlen += 2; /* displayNumber */ expectlen += 1 + 2 * connectionTypes.length; /* connectionTypes */ expectlen += 1; /* connectionAddresses */ for(i = 0; i < (int)connectionAddresses.length; i++) expectlen += 2 + connectionAddresses.data[i].length; expectlen += 2 + authenticationName.length; /* authenticationName */ expectlen += 2 + authenticationData.length; /* authenticationData */ expectlen += 1; /* authoriationNames */ for(i = 0; i < (int)authorizationNames.length; i++) expectlen += 2 + authorizationNames.data[i].length; expectlen += 2 + manufacturerDisplayID.length; /* displayID */ if(expectlen != length) { Debug("<request> length error got %d expect %d\n", length, expectlen); goto abort; } if(connectionTypes.length == 0 || connectionAddresses.length != connectionTypes.length) { reason = &noValidAddr; pdpy = 0; goto decline; } pdpy = FindProtoDisplay((XdmcpNetaddr)from, fromlen, displayNumber); if(!pdpy) { /* Check this Display against the Manager's policy */ reason = Accept(from, fromlen, displayNumber); if(reason) goto decline; /* Check the Display's stream services against Manager's policy */ i = SelectConnectionTypeIndex(&connectionTypes, &connectionAddresses); if(i < 0) { reason = &noValidAddr; goto decline; } /* The Manager considers this a new session */ connectionAddress = &connectionAddresses.data[i]; pdpy = NewProtoDisplay((XdmcpNetaddr)from, fromlen, displayNumber, connectionTypes.data[i], connectionAddress, NextSessionID()); Debug("NewProtoDisplay %p\n", pdpy); if(!pdpy) { reason = &outOfMemory; goto decline; } } if(authorizationNames.length == 0) j = 0; else j = SelectAuthorizationTypeIndex(&authenticationName, &authorizationNames); if(j < 0) { reason = &noValidAuth; goto decline; } if(!CheckAuthentication(pdpy, &manufacturerDisplayID, &authenticationName, &authenticationData)) { reason = &noAuthentic; goto decline; } if(j < (int)authorizationNames.length) { Xauth *auth; SetProtoDisplayAuthorization(pdpy, (unsigned short)authorizationNames.data[j].length, (char *)authorizationNames.data[j].data); auth = pdpy->xdmcpAuthorization; if(!auth) auth = pdpy->fileAuthorization; if(auth) { authorizationName.length = auth->name_length; authorizationName.data = (CARD8Ptr)auth->name; authorizationData.length = auth->data_length; authorizationData.data = (CARD8Ptr)auth->data; } } if(pdpy) { send_accept(from, fromlen, pdpy->sessionID, &authenticationName, &authenticationData, &authorizationName, &authorizationData, fd); } else { decline: send_decline(from, fromlen, &authenticationName, &authenticationData, reason, fd); if(pdpy) DisposeProtoDisplay(pdpy); } } abort: XdmcpDisposeARRAY16(&connectionTypes); XdmcpDisposeARRAYofARRAY8(&connectionAddresses); XdmcpDisposeARRAY8(&authenticationName); XdmcpDisposeARRAY8(&authenticationData); XdmcpDisposeARRAYofARRAY8(&authorizationNames); XdmcpDisposeARRAY8(&manufacturerDisplayID); }