static void direct_query_respond(struct sockaddr *from, int fromlen, int length, xdmOpCode type, int fd) { ARRAYofARRAY8 queryAuthenticationNames; int expectedLen; int i; if(!XdmcpReadARRAYofARRAY8(&buffer, &queryAuthenticationNames)) return; expectedLen = 1; for(i = 0; i < (int)queryAuthenticationNames.length; i++) expectedLen += 2 + queryAuthenticationNames.data[i].length; if(length == expectedLen) all_query_respond(from, fromlen, &queryAuthenticationNames, type, fd); XdmcpDisposeARRAYofARRAY8(&queryAuthenticationNames); }
static void indirect_respond(struct sockaddr *from, int fromlen, int length, int fd) { ARRAYofARRAY8 queryAuthenticationNames; ARRAY8 clientAddress; ARRAY8 clientPort; CARD16 connectionType; int expectedLen; int i; XdmcpHeader header; int localHostAsWell; Debug("<indirect> respond %d\n", length); if(!XdmcpReadARRAYofARRAY8(&buffer, &queryAuthenticationNames)) return; expectedLen = 1; for(i = 0; i < (int)queryAuthenticationNames.length; i++) expectedLen += 2 + queryAuthenticationNames.data[i].length; if(length == expectedLen) { ClientAddress(from, &clientAddress, &clientPort, &connectionType); /* * set up the forward query packet */ header.version = XDM_PROTOCOL_VERSION; header.opcode = (CARD16)FORWARD_QUERY; header.length = 0; header.length += 2 + clientAddress.length; header.length += 2 + clientPort.length; header.length += 1; for(i = 0; i < (int)queryAuthenticationNames.length; i++) header.length += 2 + queryAuthenticationNames.data[i].length; XdmcpWriteHeader(&buffer, &header); XdmcpWriteARRAY8(&buffer, &clientAddress); XdmcpWriteARRAY8(&buffer, &clientPort); XdmcpWriteARRAYofARRAY8(&buffer, &queryAuthenticationNames); localHostAsWell = ForEachMatchingIndirectHost(&clientAddress, connectionType, sendForward, (char *)fd); XdmcpDisposeARRAY8(&clientAddress); XdmcpDisposeARRAY8(&clientPort); if(localHostAsWell) all_query_respond(from, fromlen, &queryAuthenticationNames, INDIRECT_QUERY, fd); } else Debug("<indirect> length error got %d expect %d\n", length, expectedLen); XdmcpDisposeARRAYofARRAY8(&queryAuthenticationNames); }
int XdmcpReadARRAYofARRAY8 (XdmcpBufferPtr buffer, ARRAYofARRAY8Ptr array) { CARD8 i; /* * When returning FALSE, guarantee that array->data = 0. * This allows the user to safely call XdmcpDisposeARRAYofARRAY8(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 = (ARRAY8 *) malloc(array->length * sizeof (ARRAY8)); if (!array->data) return FALSE; for (i = 0; i < array->length; i++) { if (!XdmcpReadARRAY8 (buffer, &array->data[i])) { /* * We must free all of the arrays allocated thus far in the loop * and free array->data and finally set array->data = 0; * The easiest way to do this is to reset the length and call * XdmcpDisposeARRAYofARRAY8(array). */ array->length = i; XdmcpDisposeARRAYofARRAY8(array); return FALSE; } } return TRUE; }
void XdmcpRegisterAuthorizations(void) { XdmcpDisposeARRAYofARRAY8(&AuthorizationNames); RegisterAuthorizations(); }
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); }
/*ARGSUSED*/ static void forward_respond(struct sockaddr *from, int fromlen ATTR_UNUSED, int length, int fd) { ARRAY8 clientAddress; ARRAY8 clientPort; ARRAYofARRAY8 authenticationNames; struct sockaddr *client; int clientlen; int expectedLen; int i; Debug("<forward> respond %d\n", length); clientAddress.length = 0; clientAddress.data = 0; clientPort.length = 0; clientPort.data = 0; authenticationNames.length = 0; authenticationNames.data = 0; if(XdmcpReadARRAY8(&buffer, &clientAddress) && XdmcpReadARRAY8(&buffer, &clientPort) && XdmcpReadARRAYofARRAY8(&buffer, &authenticationNames)) { expectedLen = 0; expectedLen += 2 + clientAddress.length; expectedLen += 2 + clientPort.length; expectedLen += 1; /* authenticationNames */ for(i = 0; i < (int)authenticationNames.length; i++) expectedLen += 2 + authenticationNames.data[i].length; if(length == expectedLen) { int j; j = 0; for(i = 0; i < (int)clientPort.length; i++) j = j * 256 + clientPort.data[i]; Debug("<forward> client address (port %d) %[*hhu\n", j, clientAddress.length, clientAddress.data); switch(from->sa_family) { #ifdef AF_INET case AF_INET: { struct sockaddr_in in_addr; if(clientAddress.length != 4 || clientPort.length != 2) goto badAddress; bzero((char *)&in_addr, sizeof(in_addr)); #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN in_addr.sin_len = sizeof(in_addr); #endif in_addr.sin_family = AF_INET; memmove(&in_addr.sin_addr, clientAddress.data, 4); memmove((char *)&in_addr.sin_port, clientPort.data, 2); client = (struct sockaddr *)&in_addr; clientlen = sizeof(in_addr); all_query_respond(client, clientlen, &authenticationNames, FORWARD_QUERY, fd); } break; #endif #if defined(IPv6) && defined(AF_INET6) case AF_INET6: { struct sockaddr_in6 in6_addr; if(clientAddress.length != 16 || clientPort.length != 2) goto badAddress; bzero((char *)&in6_addr, sizeof(in6_addr)); #ifdef SIN6_LEN in6_addr.sin6_len = sizeof(in6_addr); #endif in6_addr.sin6_family = AF_INET6; memmove(&in6_addr, clientAddress.data, clientAddress.length); memmove((char *)&in6_addr.sin6_port, clientPort.data, 2); client = (struct sockaddr *)&in6_addr; clientlen = sizeof(in6_addr); all_query_respond(client, clientlen, &authenticationNames, FORWARD_QUERY, fd); } break; #endif #ifdef AF_UNIX case AF_UNIX: { struct sockaddr_un un_addr; if(clientAddress.length >= sizeof(un_addr.sun_path)) goto badAddress; bzero((char *)&un_addr, sizeof(un_addr)); un_addr.sun_family = AF_UNIX; memmove(un_addr.sun_path, clientAddress.data, clientAddress.length); un_addr.sun_path[clientAddress.length] = '\0'; client = (struct sockaddr *)&un_addr; #if defined(HAVE_STRUCT_SOCKADDR_IN_SIN_LEN) && !defined(__Lynx__) && defined(UNIXCONN) un_addr.sun_len = strlen(un_addr.sun_path); clientlen = SUN_LEN(&un_addr); #else clientlen = sizeof(un_addr); #endif all_query_respond(client, clientlen, &authenticationNames, FORWARD_QUERY, fd); } break; #endif #ifdef AF_CHAOS case AF_CHAOS: goto badAddress; #endif #ifdef AF_DECnet case AF_DECnet: goto badAddress; #endif } } else Debug("<forward> length error got %d expect %d\n", length, expectedLen); } badAddress: XdmcpDisposeARRAY8(&clientAddress); XdmcpDisposeARRAY8(&clientPort); XdmcpDisposeARRAYofARRAY8(&authenticationNames); }