void XdmcpRegisterConnection(int type, const char *address, int addrlen) { int i; CARD8 *newAddress; if (xdmcpGeneration != serverGeneration) { XdmcpDisposeARRAY16(&ConnectionTypes); XdmcpDisposeARRAYofARRAY8(&ConnectionAddresses); xdmcpGeneration = serverGeneration; } if (xdm_from != NULL) { /* Only register the requested address */ const void *regAddr = address; const void *fromAddr = NULL; int regAddrlen = addrlen; if (addrlen == sizeof(struct in_addr)) { if (SOCKADDR_FAMILY(FromAddress) == AF_INET) { fromAddr = &((struct sockaddr_in *) &FromAddress)->sin_addr; } #if defined(IPv6) && defined(AF_INET6) else if ((SOCKADDR_FAMILY(FromAddress) == AF_INET6) && IN6_IS_ADDR_V4MAPPED(& ((struct sockaddr_in6 *) &FromAddress)->sin6_addr)) { fromAddr = &((struct sockaddr_in6 *) &FromAddress)->sin6_addr. s6_addr[12]; } #endif } #if defined(IPv6) && defined(AF_INET6) else if (addrlen == sizeof(struct in6_addr)) { if (SOCKADDR_FAMILY(FromAddress) == AF_INET6) { fromAddr = &((struct sockaddr_in6 *) &FromAddress)->sin6_addr; } else if ((SOCKADDR_FAMILY(FromAddress) == AF_INET) && IN6_IS_ADDR_V4MAPPED((const struct in6_addr *) address)) { fromAddr = &((struct sockaddr_in *) &FromAddress)->sin_addr; regAddr = &((struct sockaddr_in6 *) &address)->sin6_addr.s6_addr[12]; regAddrlen = sizeof(struct in_addr); } } #endif if (!fromAddr || memcmp(regAddr, fromAddr, regAddrlen) != 0) { return; } } if (ConnectionAddresses.length + 1 == 256) return; newAddress = malloc(addrlen * sizeof(CARD8)); if (!newAddress) return; if (!XdmcpReallocARRAY16(&ConnectionTypes, ConnectionTypes.length + 1)) { free(newAddress); return; } if (!XdmcpReallocARRAYofARRAY8(&ConnectionAddresses, ConnectionAddresses.length + 1)) { free(newAddress); return; } ConnectionTypes.data[ConnectionTypes.length - 1] = (CARD16) type; for (i = 0; i < addrlen; i++) newAddress[i] = address[i]; ConnectionAddresses.data[ConnectionAddresses.length - 1].data = newAddress; ConnectionAddresses.data[ConnectionAddresses.length - 1].length = addrlen; }
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); }