/** Process a general attribute request message. * * @param[in] message - The message to process. * @param[out] sendbuf - The response buffer to fill. * @param[in] errorcode - The error code from the client request. * * @return Zero on success, or a non-zero SLP error on failure. * * @internal */ static int ProcessAttrRqst(SLPMessage * message, SLPBuffer * sendbuf, int errorcode) { SLPDDatabaseAttrRqstResult * db = 0; size_t size = 0; SLPBuffer result = *sendbuf; #ifdef ENABLE_SLPv2_SECURITY int i; uint8_t * generatedauth = 0; int generatedauthlen = 0; uint8_t * opaqueauth = 0; int opaqueauthlen = 0; #endif /* if errorcode is set, we can not be sure that message is good Go directly to send response code */ if (errorcode) goto RESPOND; /* check for one of our IP addresses in the prlist */ if (SLPIntersectStringList(message->body.attrrqst.prlistlen, message->body.attrrqst.prlist, G_SlpdProperty.interfacesLen, G_SlpdProperty.interfaces)) { /* Silently ignore */ result->end = result->start; goto FINISHED; } /* make sure that we handle the scope */ if (SLPIntersectStringList(message->body.attrrqst.scopelistlen, message->body.attrrqst.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes)) { /* Make sure that we handle at least verify registrations made with the requested SPI. If we can't then have to return an error because there is no way we can return URL entries that ares signed in a way the requester can understand */ #ifdef ENABLE_SLPv2_SECURITY if (G_SlpdProperty.securityEnabled) { if (message->body.attrrqst.taglistlen == 0) { /* We can send back entire attribute strings without generating a new attribute authentication block we just use the one sent by the registering agent which we have to have been able to verify */ if (SLPSpiCanVerify(G_SlpdSpiHandle, message->body.attrrqst.spistrlen, message->body.attrrqst.spistr) == 0) { errorcode = SLP_ERROR_AUTHENTICATION_UNKNOWN; goto RESPOND; } } else { /* We have to be able to *generate* (sign) authentication blocks for attrrqst with taglists since it is possible that the returned attributes are a subset of what the original registering agent sent */ if (SLPSpiCanSign(G_SlpdSpiHandle, message->body.attrrqst.spistrlen, message->body.attrrqst.spistr) == 0) { errorcode = SLP_ERROR_AUTHENTICATION_UNKNOWN; goto RESPOND; } } } else { if (message->body.attrrqst.spistrlen) { errorcode = SLP_ERROR_AUTHENTICATION_UNKNOWN; goto RESPOND; } } #else if (message->body.attrrqst.spistrlen) { errorcode = SLP_ERROR_AUTHENTICATION_UNKNOWN; goto RESPOND; } #endif /* Find attributes in the database */ errorcode = SLPDDatabaseAttrRqstStart(message,&db); } else errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED; RESPOND: /* do not send error codes or empty replies to multicast requests */ if (errorcode != 0 || db->attrlistlen == 0) { if (message->header.flags & SLP_FLAG_MCAST || SLPNetIsMCast(&(message->peer))) { result->end = result->start; goto FINISHED; } } /* ensure the buffer is big enough to handle the whole attrrply */ size = message->header.langtaglen + 19; /* 14 bytes for header */ /* 2 bytes for error code */ /* 2 bytes for attr-list len */ /* 1 byte for the authcount */ if (errorcode == 0) { size += db->attrlistlen; #ifdef ENABLE_SLPv2_SECURITY /* Generate authblock if necessary or just use the one was included by registering agent. Reserve sufficent space for either case. */ if (G_SlpdProperty.securityEnabled && message->body.attrrqst.spistrlen) { if (message->body.attrrqst.taglistlen == 0) { for (i = 0; i < db->authcount; i++) { if (SLPCompareString(db->autharray[i].spistrlen, db->autharray[i].spistr, message->body.attrrqst.spistrlen, message->body.attrrqst.spistr) == 0) { opaqueauth = db->autharray[i].opaque; opaqueauthlen = db->autharray[i].opaquelen; break; } } } else { errorcode = SLPAuthSignString(G_SlpdSpiHandle, message->body.attrrqst.spistrlen, message->body.attrrqst.spistr, db->attrlistlen, db->attrlist, &generatedauthlen, &generatedauth); opaqueauthlen = generatedauthlen; opaqueauth = generatedauth; } size += opaqueauthlen; } #endif } /* alloc the buffer */ result = SLPBufferRealloc(result, size); if (result == 0) { errorcode = SLP_ERROR_INTERNAL_ERROR; goto FINISHED; } /* Add the header */ /* version */ *result->curpos++ = 2; /* function id */ *result->curpos++ = SLP_FUNCT_ATTRRPLY; /* length */ PutUINT24(&result->curpos, size); /* flags */ PutUINT16(&result->curpos, (size > (size_t)G_SlpdProperty.MTU? SLP_FLAG_OVERFLOW: 0)); /* ext offset */ PutUINT24(&result->curpos, 0); /* xid */ PutUINT16(&result->curpos, message->header.xid); /* lang tag len */ PutUINT16(&result->curpos, message->header.langtaglen); /* lang tag */ memcpy(result->curpos, message->header.langtag, message->header.langtaglen); result->curpos += message->header.langtaglen; /* Add rest of the AttrRqst */ /* error code*/ PutUINT16(&result->curpos, errorcode); if (errorcode == 0) { /* attr-list len */ PutUINT16(&result->curpos, db->attrlistlen); if (db->attrlistlen) memcpy(result->curpos, db->attrlist, db->attrlistlen); result->curpos += db->attrlistlen; /* authentication block */ #ifdef ENABLE_SLPv2_SECURITY if (opaqueauth) { /* authcount */ *result->curpos++ = 1; memcpy(result->curpos, opaqueauth, opaqueauthlen); result->curpos += opaqueauthlen; } else #endif *result->curpos++ = 0; /* authcount */ } FINISHED: #ifdef ENABLE_SLPv2_SECURITY /* free the generated authblock if any */ xfree(generatedauth); #endif if (db) SLPDDatabaseAttrRqstEnd(db); *sendbuf = result; return errorcode; }
/*-------------------------------------------------------------------------*/ int v1ProcessAttrRqst(struct sockaddr_in* peeraddr, SLPMessage message, SLPBuffer* sendbuf, int errorcode) /*-------------------------------------------------------------------------*/ { SLPDDatabaseAttrRqstResult* db = 0; int attrlen = 0; int size = 0; SLPBuffer result = *sendbuf; /*--------------------------------------------------------------*/ /* If errorcode is set, we can not be sure that message is good */ /* Go directly to send response code */ /*--------------------------------------------------------------*/ if (errorcode) { goto RESPOND; } /*-------------------------------------------------*/ /* Check for one of our IP addresses in the prlist */ /*-------------------------------------------------*/ if (SLPIntersectStringList(message->body.attrrqst.prlistlen, message->body.attrrqst.prlist, G_SlpdProperty.interfacesLen, G_SlpdProperty.interfaces)) { result->end = result->start; goto FINISHED; } /*------------------------------------*/ /* Make sure that we handle the scope */ /*------ -----------------------------*/ if (SLPIntersectStringList(message->body.attrrqst.scopelistlen, message->body.attrrqst.scopelist, G_SlpdProperty.useScopesLen, G_SlpdProperty.useScopes)) { /*---------------------------------*/ /* Find attributes in the database */ /*---------------------------------*/ errorcode = SLPDDatabaseAttrRqstStart(message,&db); } else { errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED; } RESPOND: /*----------------------------------------------------------------*/ /* Do not send error codes or empty replies to multicast requests */ /*----------------------------------------------------------------*/ if (message->header.flags & SLP_FLAG_MCAST) { if (errorcode != 0 || db->attrlistlen == 0) { result->end = result->start; goto FINISHED; } } /*--------------------------------------------------------------*/ /* ensure the buffer is big enough to handle the whole attrrply */ /*--------------------------------------------------------------*/ size = 16; /* 12 bytes for header, 2 bytes for error code, 2 bytes for attr-list len */ if (errorcode == 0) { attrlen = INT_MAX; errorcode = SLPv1ToEncoding(0, &attrlen, message->header.encoding, db->attrlist, db->attrlistlen); size += attrlen; } /*-------------------*/ /* Alloc the buffer */ /*-------------------*/ result = SLPBufferRealloc(result,size); if (result == 0) { errorcode = SLP_ERROR_INTERNAL_ERROR; goto FINISHED; } /*----------------*/ /* Add the header */ /*----------------*/ /*version*/ *(result->start) = 1; /*function id*/ *(result->start + 1) = SLP_FUNCT_ATTRRPLY; /*length*/ ToUINT16(result->start + 2, size); /*flags - TODO set the flags correctly */ *(result->start + 4) = message->header.flags | (size > SLP_MAX_DATAGRAM_SIZE ? SLPv1_FLAG_OVERFLOW : 0); /*dialect*/ *(result->start + 5) = 0; /*language code*/ memcpy(result->start + 6, message->header.langtag, 2); ToUINT16(result->start + 8, message->header.encoding); /*xid*/ ToUINT16(result->start + 10, message->header.xid); /*--------------------------*/ /* Add rest of the AttrRply */ /*--------------------------*/ result->curpos = result->start + 12; /* error code*/ ToUINT16(result->curpos, errorcode); result->curpos = result->curpos + 2; if (errorcode == 0) { /* attr-list len */ ToUINT16(result->curpos, attrlen); result->curpos = result->curpos + 2; attrlen = size; SLPv1ToEncoding(result->curpos, &attrlen, message->header.encoding, db->attrlist, db->attrlistlen); result->curpos = result->curpos + attrlen; } FINISHED: *sendbuf = result; if (db) SLPDDatabaseAttrRqstEnd(db); return errorcode; }