ARRAY8Ptr IndirectChoice ( ARRAY8Ptr clientAddress, CARD16 connectionType) { ChoicePtr c, next, prev; long now; now = time (0); prev = 0; for (c = choices; c; c = next) { next = c->next; if (now - c->time > 15) { Debug ("Timeout choice\n"); if (prev) prev->next = next; else choices = next; XdmcpDisposeARRAY8 (&c->client); XdmcpDisposeARRAY8 (&c->choice); free ((char *) c); } else { if (XdmcpARRAY8Equal (clientAddress, &c->client) && connectionType == c->connectionType) return &c->choice; prev = c; } } return 0; }
static void recv_decline_msg(unsigned length) { ARRAY8 status, DeclineAuthenticationName, DeclineAuthenticationData; status.data = 0; DeclineAuthenticationName.data = 0; DeclineAuthenticationData.data = 0; if (XdmcpReadARRAY8 (&buffer, &status) && XdmcpReadARRAY8 (&buffer, &DeclineAuthenticationName) && XdmcpReadARRAY8 (&buffer, &DeclineAuthenticationData)) { if (length == 6 + status.length + DeclineAuthenticationName.length + DeclineAuthenticationData.length && XdmcpCheckAuthentication (&DeclineAuthenticationName, &DeclineAuthenticationData, DECLINE)) { XdmcpFatal ("Session declined", &status); } } XdmcpDisposeARRAY8 (&status); XdmcpDisposeARRAY8 (&DeclineAuthenticationName); XdmcpDisposeARRAY8 (&DeclineAuthenticationData); }
static int RegisterIndirectChoice ( ARRAY8Ptr clientAddress, CARD16 connectionType, ARRAY8Ptr choice) { ChoicePtr c; int insert; int found; Debug ("Got indirect choice back (%s)\n", Print8Address(clientAddress)); for (c = choices; c; c = c->next) { if (XdmcpARRAY8Equal (clientAddress, &c->client) && connectionType == c->connectionType) { found = 1; break; } } if (!found) return 0; insert = 0; if (!c) { c = (ChoicePtr) malloc (sizeof (ChoiceRec)); insert = 1; if (!c) return 0; c->connectionType = connectionType; if (!XdmcpCopyARRAY8 (clientAddress, &c->client)) { free ((char *) c); return 0; } } else { XdmcpDisposeARRAY8 (&c->choice); } if (!XdmcpCopyARRAY8 (choice, &c->choice)) { XdmcpDisposeARRAY8 (&c->client); free ((char *) c); return 0; } if (insert) { c->next = choices; choices = c; } c->time = time (0); Debug("choice=(%s)\n", Print8Address(choice)); return 1; }
static void recv_accept_msg(unsigned length) { CARD32 AcceptSessionID; ARRAY8 AcceptAuthenticationName, AcceptAuthenticationData; ARRAY8 AcceptAuthorizationName, AcceptAuthorizationData; if (state != XDM_AWAIT_REQUEST_RESPONSE) return; AcceptAuthenticationName.data = 0; AcceptAuthenticationData.data = 0; AcceptAuthorizationName.data = 0; AcceptAuthorizationData.data = 0; if (XdmcpReadCARD32 (&buffer, &AcceptSessionID) && XdmcpReadARRAY8 (&buffer, &AcceptAuthenticationName) && XdmcpReadARRAY8 (&buffer, &AcceptAuthenticationData) && XdmcpReadARRAY8 (&buffer, &AcceptAuthorizationName) && XdmcpReadARRAY8 (&buffer, &AcceptAuthorizationData)) { if (length == 12 + AcceptAuthenticationName.length + AcceptAuthenticationData.length + AcceptAuthorizationName.length + AcceptAuthorizationData.length) { if (!XdmcpCheckAuthentication (&AcceptAuthenticationName, &AcceptAuthenticationData, ACCEPT)) { XdmcpFatal ("Authentication Failure", &AcceptAuthenticationName); } /* permit access control manipulations from this host */ AugmentSelf (&req_sockaddr, req_socklen); /* if the authorization specified in the packet fails * to be acceptable, enable the local addresses */ if (!XdmcpAddAuthorization (&AcceptAuthorizationName, &AcceptAuthorizationData)) { AddLocalHosts (); } SessionID = AcceptSessionID; state = XDM_MANAGE; send_packet(); } } XdmcpDisposeARRAY8 (&AcceptAuthenticationName); XdmcpDisposeARRAY8 (&AcceptAuthenticationData); XdmcpDisposeARRAY8 (&AcceptAuthorizationName); XdmcpDisposeARRAY8 (&AcceptAuthorizationData); }
static void all_query_respond(struct sockaddr *from, int fromlen, ARRAYofARRAY8Ptr authenticationNames, xdmOpCode type, int fd) { ARRAY8Ptr authenticationName; ARRAY8 status; ARRAY8 addr; CARD16 connectionType; int family; int length; family = ConvertAddr((XdmcpNetaddr)from, &length, &(addr.data)); addr.length = length; /* convert int to short */ Debug("all_query_respond: conntype=%d, addr=%02[*:hhx\n", family, addr.length, addr.data); if(family < 0) return; connectionType = family; if(type == INDIRECT_QUERY) RememberIndirectClient(&addr, connectionType); else ForgetIndirectClient(&addr, connectionType); authenticationName = ChooseAuthentication(authenticationNames); if(Willing(&addr, connectionType, authenticationName, &status, type)) send_willing(from, fromlen, authenticationName, &status, fd); else if(type == QUERY) send_unwilling(from, fromlen, authenticationName, &status, fd); XdmcpDisposeARRAY8(&status); }
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); }
void XdmcpRegisterAuthentication ( char *name, int namelen, char *data, int datalen, ValidatorFunc Validator, GeneratorFunc Generator, AddAuthorFunc AddAuth) { int i; ARRAY8 AuthenticationName, AuthenticationData; static AuthenticationFuncsPtr newFuncs; if (!XdmcpAllocARRAY8 (&AuthenticationName, namelen)) return; if (!XdmcpAllocARRAY8 (&AuthenticationData, datalen)) { XdmcpDisposeARRAY8 (&AuthenticationName); return; } for (i = 0; i < namelen; i++) AuthenticationName.data[i] = name[i]; for (i = 0; i < datalen; i++) AuthenticationData.data[i] = data[i]; if (!(XdmcpReallocARRAYofARRAY8 (&AuthenticationNames, AuthenticationNames.length + 1) && XdmcpReallocARRAYofARRAY8 (&AuthenticationDatas, AuthenticationDatas.length + 1) && (newFuncs = (AuthenticationFuncsPtr) xalloc ( (AuthenticationNames.length + 1) * sizeof (AuthenticationFuncsRec))))) { XdmcpDisposeARRAY8 (&AuthenticationName); XdmcpDisposeARRAY8 (&AuthenticationData); return; } for (i = 0; i < AuthenticationNames.length - 1; i++) newFuncs[i] = AuthenticationFuncsList[i]; newFuncs[AuthenticationNames.length-1].Validator = Validator; newFuncs[AuthenticationNames.length-1].Generator = Generator; newFuncs[AuthenticationNames.length-1].AddAuth = AddAuth; xfree (AuthenticationFuncsList); AuthenticationFuncsList = newFuncs; AuthenticationNames.data[AuthenticationNames.length-1] = AuthenticationName; AuthenticationDatas.data[AuthenticationDatas.length-1] = AuthenticationData; }
static void XdmcpRegisterManufacturerDisplayID(const char *name, int length) { int i; XdmcpDisposeARRAY8(&ManufacturerDisplayID); if (!XdmcpAllocARRAY8(&ManufacturerDisplayID, length)) return; for (i = 0; i < length; i++) ManufacturerDisplayID.data[i] = (CARD8) name[i]; }
static void XdmcpRegisterDisplayClass(const char *name, int length) { int i; XdmcpDisposeARRAY8(&DisplayClass); if (!XdmcpAllocARRAY8(&DisplayClass, length)) return; for (i = 0; i < length; i++) DisplayClass.data[i] = (CARD8) name[i]; }
static void recv_willing_msg( struct sockaddr *from, int fromlen, unsigned length) { ARRAY8 authenticationName; ARRAY8 hostname; ARRAY8 status; authenticationName.data = 0; hostname.data = 0; status.data = 0; if (XdmcpReadARRAY8 (&buffer, &authenticationName) && XdmcpReadARRAY8 (&buffer, &hostname) && XdmcpReadARRAY8 (&buffer, &status)) { if (length == 6 + authenticationName.length + hostname.length + status.length) { switch (state) { case XDM_COLLECT_QUERY: XdmcpSelectHost(from, fromlen, &authenticationName); break; case XDM_COLLECT_BROADCAST_QUERY: #if defined(IPv6) && defined(AF_INET6) case XDM_COLLECT_MULTICAST_QUERY: #endif case XDM_COLLECT_INDIRECT_QUERY: XdmcpAddHost(from, fromlen, &authenticationName, &hostname, &status); break; default: break; } } } XdmcpDisposeARRAY8 (&authenticationName); XdmcpDisposeARRAY8 (&hostname); XdmcpDisposeARRAY8 (&status); }
void RemoveDisplay(struct display *old) { struct display *d, **dp; int i; for(dp = &displays; (d = *dp); dp = &(*dp)->next) { if(d == old) { Debug("Removing display %s\n", d->name); *dp = d->next; IfFree(d->class2); IfFree(d->cfg.data); delStr(d->cfg.dep.name); #ifdef XDMCP IfFree(d->remoteHost); #endif if(d->authorizations) { for(i = 0; i < d->authNum; i++) XauDisposeAuth(d->authorizations[i]); free((char *)d->authorizations); } if(d->authFile) { (void)unlink(d->authFile); free(d->authFile); } IfFree(d->authNameLens); #ifdef XDMCP XdmcpDisposeARRAY8(&d->peer); XdmcpDisposeARRAY8(&d->from); XdmcpDisposeARRAY8(&d->clientAddr); #endif free((char *)d); break; } } }
static void FreeHostEntry (HostEntry *h) { switch (h->type) { case HOST_ALIAS: free (h->entry.aliasName); break; case HOST_ADDRESS: XdmcpDisposeARRAY8 (&h->entry.hostAddress); break; case HOST_CHOOSER: break; } free (h); }
static void recv_failed_msg(unsigned length) { CARD32 FailedSessionID; ARRAY8 status; if (state != XDM_AWAIT_MANAGE_RESPONSE) return; status.data = 0; if (XdmcpReadCARD32(&buffer, &FailedSessionID) && XdmcpReadARRAY8(&buffer, &status)) { if (length == 6 + status.length && SessionID == FailedSessionID) { XdmcpFatal("Session failed", &status); } } XdmcpDisposeARRAY8(&status); }
static void freeDisplay(struct display *d) { char **x; int i; IfFree(d->name); IfFree(d->class); for (x = d->argv; x && *x; x++) IfFree(*x); IfFree(d->argv); IfFree(d->resources); IfFree(d->xrdb); IfFree(d->setup); IfFree(d->startup); IfFree(d->reset); IfFree(d->session); IfFree(d->userPath); IfFree(d->systemPath); IfFree(d->systemShell); IfFree(d->failsafeClient); IfFree(d->chooser); if (d->authorizations) { for (i = 0; i < d->authNum; i++) XauDisposeAuth(d->authorizations[i]); free(d->authorizations); } IfFree(d->clientAuthFile); if (d->authFile) (void)unlink(d->authFile); IfFree(d->authFile); IfFree(d->userAuthDir); for (x = d->authNames; x && *x; x++) IfFree(*x); IfFree(d->authNames); IfFree(d->authNameLens); #ifdef XDMCP IfFree(d->peer); IfFree(d->from); XdmcpDisposeARRAY8(&d->clientAddr); #endif free(d); }
static void FreeDisplayEntry (DisplayEntry *d) { HostEntry *h, *next; switch (d->type) { case DISPLAY_ALIAS: free (d->entry.aliasName); break; case DISPLAY_PATTERN: free (d->entry.displayPattern); break; case DISPLAY_ADDRESS: XdmcpDisposeARRAY8 (&d->entry.displayAddress.clientAddress); break; } for (h = d->hosts; h; h = next) { next = h->next; FreeHostEntry (h); } free ((char *) d); }
ForgetIndirectClient ( ARRAY8Ptr clientAddress, CARD16 connectionType) { IndirectUsersPtr i, prev; prev = 0; for (i = indirectUsers; i; i = i->next) { if (XdmcpARRAY8Equal (clientAddress, &i->client) && connectionType == i->connectionType) { if (prev) prev->next = i->next; else indirectUsers = i->next; XdmcpDisposeARRAY8 (&i->client); free ((char *) i); break; } prev = i; } }
static void FreeDisplayEntry (DisplayEntry *d) { HostEntry *h, *next; switch (d->type) { case DISPLAY_ALIAS: free (d->entry.aliasName); break; case DISPLAY_PATTERN: free (d->entry.displayPattern); break; case DISPLAY_ADDRESS: XdmcpDisposeARRAY8 (&d->entry.displayAddress.clientAddress); break; case DISPLAY_LISTEN: /* do nothing - this case doesn't use the d->entry union */ break; } for (h = d->hosts; h; h = next) { next = h->next; FreeHostEntry (h); } free (d); }
static void processDPipe( struct display *d ) { char *user, *pass, *args; int cmd; GTalk dpytalk; #ifdef XDMCP int ct, len; ARRAY8 ca, ha; #endif dpytalk.pipe = &d->pipe; if (Setjmp( dpytalk.errjmp )) { StopDisplay( d ); return; } GSet( &dpytalk ); if (!GRecvCmd( &cmd )) { /* process already exited */ UnregisterInput( d->pipe.rfd ); return; } switch (cmd) { case D_User: d->userSess = GRecvInt(); d->userName = GRecvStr(); d->sessName = GRecvStr(); break; case D_ReLogin: user = GRecvStr(); pass = GRecvStr(); args = GRecvStr(); setNLogin( d, user, pass, args, 1 ); free( args ); free( pass ); free( user ); break; #ifdef XDMCP case D_ChooseHost: ca.data = (unsigned char *)GRecvArr( &len ); ca.length = (CARD16)len; ct = GRecvInt(); ha.data = (unsigned char *)GRecvArr( &len ); ha.length = (CARD16)len; RegisterIndirectChoice( &ca, ct, &ha ); XdmcpDisposeARRAY8( &ha ); XdmcpDisposeARRAY8( &ca ); break; case D_RemoteHost: if (d->remoteHost) free( d->remoteHost ); d->remoteHost = GRecvStr(); break; #endif case D_XConnOk: startingServer = 0; break; default: LogError( "Internal error: unknown D_* command %d\n", cmd ); StopDisplay( d ); break; } }
/*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); }
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); }
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 send_request_msg(void) { XdmcpHeader header; int length; int i; CARD16 XdmcpConnectionType; ARRAY8 authenticationData; int socketfd = xdmcpSocket; switch (SOCKADDR_FAMILY(ManagerAddress)) { case AF_INET: XdmcpConnectionType = FamilyInternet; break; #if defined(IPv6) && defined(AF_INET6) case AF_INET6: XdmcpConnectionType = FamilyInternet6; break; #endif default: XdmcpConnectionType = 0xffff; break; } header.version = XDM_PROTOCOL_VERSION; header.opcode = (CARD16) REQUEST; length = 2; /* display number */ length += 1 + 2 * ConnectionTypes.length; /* connection types */ length += 1; /* connection addresses */ for (i = 0; i < ConnectionAddresses.length; i++) length += 2 + ConnectionAddresses.data[i].length; authenticationData.length = 0; authenticationData.data = 0; if (AuthenticationFuncs) { (*AuthenticationFuncs->Generator) (AuthenticationData, &authenticationData, REQUEST); } length += 2 + AuthenticationName->length; /* authentication name */ length += 2 + authenticationData.length; /* authentication data */ length += 1; /* authorization names */ for (i = 0; i < AuthorizationNames.length; i++) length += 2 + AuthorizationNames.data[i].length; length += 2 + ManufacturerDisplayID.length; /* display ID */ header.length = length; if (!XdmcpWriteHeader(&buffer, &header)) { XdmcpDisposeARRAY8(&authenticationData); return; } XdmcpWriteCARD16(&buffer, DisplayNumber); XdmcpWriteCARD8(&buffer, ConnectionTypes.length); /* The connection array is send reordered, so that connections of */ /* the same address type as the XDMCP manager connection are send */ /* first. This works around a bug in xdm. [email protected] */ for (i = 0; i < (int) ConnectionTypes.length; i++) if (ConnectionTypes.data[i] == XdmcpConnectionType) XdmcpWriteCARD16(&buffer, ConnectionTypes.data[i]); for (i = 0; i < (int) ConnectionTypes.length; i++) if (ConnectionTypes.data[i] != XdmcpConnectionType) XdmcpWriteCARD16(&buffer, ConnectionTypes.data[i]); XdmcpWriteCARD8(&buffer, ConnectionAddresses.length); for (i = 0; i < (int) ConnectionAddresses.length; i++) if ((i < ConnectionTypes.length) && (ConnectionTypes.data[i] == XdmcpConnectionType)) XdmcpWriteARRAY8(&buffer, &ConnectionAddresses.data[i]); for (i = 0; i < (int) ConnectionAddresses.length; i++) if ((i >= ConnectionTypes.length) || (ConnectionTypes.data[i] != XdmcpConnectionType)) XdmcpWriteARRAY8(&buffer, &ConnectionAddresses.data[i]); XdmcpWriteARRAY8(&buffer, AuthenticationName); XdmcpWriteARRAY8(&buffer, &authenticationData); XdmcpDisposeARRAY8(&authenticationData); XdmcpWriteARRAYofARRAY8(&buffer, &AuthorizationNames); XdmcpWriteARRAY8(&buffer, &ManufacturerDisplayID); #if defined(IPv6) && defined(AF_INET6) if (SOCKADDR_FAMILY(req_sockaddr) == AF_INET6) socketfd = xdmcpSocket6; #endif if (XdmcpFlush(socketfd, &buffer, (XdmcpNetaddr) &req_sockaddr, req_socklen)) state = XDM_AWAIT_REQUEST_RESPONSE; }
static void processDPipe(struct display *d) { char *user, *pass, *args; int cmd; GTalk dpytalk; #ifdef XDMCP int ct, len; ARRAY8 ca, cp, ha; #endif dpytalk.pipe = &d->pipe; if (Setjmp(dpytalk.errjmp)) { stopDisplay(d); return; } gSet(&dpytalk); if (!gRecvCmd(&cmd)) { /* process already exited */ unregisterInput(d->pipe.fd.r); return; } switch (cmd) { case D_User: d->userSess = gRecvInt(); d->userName = gRecvStr(); d->sessName = gRecvStr(); break; case D_UnUser: sessionDone(d); if (d->sdRec.how) { if (d->sdRec.force == SHUT_ASK && (anyUserLogins(-1) || d->allowShutdown == SHUT_ROOT)) { gSendInt(True); } else { if (!sdRec.how || sdRec.force != SHUT_FORCE || !((d->allowNuke == SHUT_NONE && sdRec.uid != d->sdRec.uid) || (d->allowNuke == SHUT_ROOT && d->sdRec.uid))) { free(sdRec.osname); sdRec = d->sdRec; } else { free(d->sdRec.osname); } d->sdRec.how = 0; d->sdRec.osname = 0; gSendInt(False); } } else { gSendInt(False); } break; case D_ReLogin: user = gRecvStr(); pass = gRecvStr(); args = gRecvStr(); setNLogin(d, user, pass, args, 1); free(args); free(pass); free(user); break; #ifdef XDMCP case D_ChooseHost: ca.data = (unsigned char *)gRecvArr(&len); ca.length = (CARD16)len; cp.data = (unsigned char *)gRecvArr(&len); cp.length = (CARD16)len; ct = gRecvInt(); ha.data = (unsigned char *)gRecvArr(&len); ha.length = (CARD16)len; registerIndirectChoice(&ca, &cp, ct, &ha); XdmcpDisposeARRAY8(&ha); XdmcpDisposeARRAY8(&cp); XdmcpDisposeARRAY8(&ca); break; case D_RemoteHost: free(d->remoteHost); d->remoteHost = gRecvStr(); break; #endif case D_XConnOk: startingServer = 0; break; default: logError("Internal error: unknown D_* command %d\n", cmd); stopDisplay(d); break; } }