You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1504 lines
54 KiB
1504 lines
54 KiB
4 years ago
|
/**************************************************************************/
|
||
|
/* */
|
||
|
/* Project: OpenSLP - OpenSource implementation of Service Location */
|
||
|
/* Protocol Version 2 */
|
||
|
/* */
|
||
|
/* File: slpd_process.c */
|
||
|
/* */
|
||
|
/* Abstract: Processes incoming SLP messages */
|
||
|
/* */
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
/* */
|
||
|
/* Please submit patches to http://www.openslp.org */
|
||
|
/* */
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
/* */
|
||
|
/* Copyright (C) 2000 Caldera Systems, Inc */
|
||
|
/* All rights reserved. */
|
||
|
/* */
|
||
|
/* Redistribution and use in source and binary forms, with or without */
|
||
|
/* modification, are permitted provided that the following conditions are */
|
||
|
/* met: */
|
||
|
/* */
|
||
|
/* Redistributions of source code must retain the above copyright */
|
||
|
/* notice, this list of conditions and the following disclaimer. */
|
||
|
/* */
|
||
|
/* Redistributions in binary form must reproduce the above copyright */
|
||
|
/* notice, this list of conditions and the following disclaimer in */
|
||
|
/* the documentation and/or other materials provided with the */
|
||
|
/* distribution. */
|
||
|
/* */
|
||
|
/* Neither the name of Caldera Systems nor the names of its */
|
||
|
/* contributors may be used to endorse or promote products derived */
|
||
|
/* from this software without specific prior written permission. */
|
||
|
/* */
|
||
|
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
|
||
|
/* `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
|
||
|
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
|
||
|
/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CALDERA */
|
||
|
/* SYSTEMS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
|
||
|
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
|
||
|
/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
|
||
|
/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
|
||
|
/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
|
||
|
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
|
||
|
/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||
|
/* */
|
||
|
/***************************************************************************/
|
||
|
|
||
|
/*=========================================================================*/
|
||
|
/* slpd includes */
|
||
|
/*=========================================================================*/
|
||
|
#include "slpd_process.h"
|
||
|
#include "slpd_property.h"
|
||
|
#include "slpd_database.h"
|
||
|
#include "slpd_knownda.h"
|
||
|
#include "slpd_log.h"
|
||
|
#ifdef ENABLE_SLPv2_SECURITY
|
||
|
#include "slpd_spi.h"
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/*=========================================================================*/
|
||
|
/* common code includes */
|
||
|
/*=========================================================================*/
|
||
|
#include "slp_xmalloc.h"
|
||
|
#include "slp_message.h"
|
||
|
#include "slp_compare.h"
|
||
|
#ifdef ENABLE_SLPv2_SECURITY
|
||
|
#include "slp_auth.h"
|
||
|
#endif
|
||
|
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
int ProcessSASrvRqst(SLPMessage message,
|
||
|
SLPBuffer* sendbuf,
|
||
|
int errorcode)
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
{
|
||
|
int size = 0;
|
||
|
SLPBuffer result = *sendbuf;
|
||
|
|
||
|
if (message->body.srvrqst.scopelistlen == 0 ||
|
||
|
SLPIntersectStringList(message->body.srvrqst.scopelistlen,
|
||
|
message->body.srvrqst.scopelist,
|
||
|
G_SlpdProperty.useScopesLen,
|
||
|
G_SlpdProperty.useScopes) != 0)
|
||
|
{
|
||
|
/*----------------------*/
|
||
|
/* Send back a SAAdvert */
|
||
|
/*----------------------*/
|
||
|
|
||
|
/*--------------------------------------------------------------*/
|
||
|
/* ensure the buffer is big enough to handle the whole SAAdvert */
|
||
|
/*--------------------------------------------------------------*/
|
||
|
size = message->header.langtaglen + 21; /* 14 bytes for header */
|
||
|
/* 2 bytes for url count */
|
||
|
/* 2 bytes for scope list len */
|
||
|
/* 2 bytes for attr list len */
|
||
|
/* 1 byte for authblock count */
|
||
|
size += G_SlpdProperty.myUrlLen;
|
||
|
size += G_SlpdProperty.useScopesLen;
|
||
|
/* TODO: size += G_SlpdProperty.SAAttributes */
|
||
|
|
||
|
result = SLPBufferRealloc(result,size);
|
||
|
if (result == 0)
|
||
|
{
|
||
|
/* TODO: out of memory, what should we do here! */
|
||
|
errorcode = SLP_ERROR_INTERNAL_ERROR;
|
||
|
goto FINISHED;
|
||
|
}
|
||
|
|
||
|
/*----------------*/
|
||
|
/* Add the header */
|
||
|
/*----------------*/
|
||
|
/*version*/
|
||
|
*(result->start) = 2;
|
||
|
/*function id*/
|
||
|
*(result->start + 1) = SLP_FUNCT_SAADVERT;
|
||
|
/*length*/
|
||
|
ToUINT24(result->start + 2, size);
|
||
|
/*flags*/
|
||
|
ToUINT16(result->start + 5,
|
||
|
(size > SLP_MAX_DATAGRAM_SIZE ? SLP_FLAG_OVERFLOW : 0));
|
||
|
/*ext offset*/
|
||
|
ToUINT24(result->start + 7,0);
|
||
|
/*xid*/
|
||
|
ToUINT16(result->start + 10,message->header.xid);
|
||
|
/*lang tag len*/
|
||
|
ToUINT16(result->start + 12,message->header.langtaglen);
|
||
|
/*lang tag*/
|
||
|
memcpy(result->start + 14,
|
||
|
message->header.langtag,
|
||
|
message->header.langtaglen);
|
||
|
|
||
|
/*--------------------------*/
|
||
|
/* Add rest of the SAAdvert */
|
||
|
/*--------------------------*/
|
||
|
result->curpos = result->start + 14 + message->header.langtaglen;
|
||
|
/* url len */
|
||
|
ToUINT16(result->curpos, G_SlpdProperty.myUrlLen);
|
||
|
result->curpos = result->curpos + 2;
|
||
|
/* url */
|
||
|
memcpy(result->curpos,G_SlpdProperty.myUrl,G_SlpdProperty.myUrlLen);
|
||
|
result->curpos = result->curpos + G_SlpdProperty.myUrlLen;
|
||
|
/* scope list len */
|
||
|
ToUINT16(result->curpos, G_SlpdProperty.useScopesLen);
|
||
|
result->curpos = result->curpos + 2;
|
||
|
/* scope list */
|
||
|
memcpy(result->curpos,G_SlpdProperty.useScopes,G_SlpdProperty.useScopesLen);
|
||
|
result->curpos = result->curpos + G_SlpdProperty.useScopesLen;
|
||
|
/* attr list len */
|
||
|
/* ToUINT16(result->curpos,G_SlpdProperty.SAAttributesLen) */
|
||
|
ToUINT16(result->curpos, 0);
|
||
|
result->curpos = result->curpos + 2;
|
||
|
/* attr list */
|
||
|
/* memcpy(result->start,G_SlpdProperty.SAAttributes,G_SlpdProperty.SAAttributesLen) */
|
||
|
/* authblock count */
|
||
|
*(result->curpos) = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;
|
||
|
}
|
||
|
|
||
|
FINISHED:
|
||
|
|
||
|
*sendbuf = result;
|
||
|
|
||
|
return errorcode;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
int ProcessDASrvRqst(SLPMessage message,
|
||
|
SLPBuffer* sendbuf,
|
||
|
int errorcode)
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
{
|
||
|
SLPBuffer tmp = 0;
|
||
|
SLPMessage msg = 0;
|
||
|
void* eh = 0;
|
||
|
|
||
|
/*---------------------------------------------------------------------*/
|
||
|
/* Special case for when libslp asks slpd (through the loopback) about */
|
||
|
/* a known DAs. Fill sendbuf with DAAdverts from all known DAs. */
|
||
|
/*---------------------------------------------------------------------*/
|
||
|
if (ISLOCAL(message->peer.sin_addr))
|
||
|
{
|
||
|
/* TODO: be smarter about how much memory is allocated here! */
|
||
|
/* 4096 may not be big enough to handle all DAAdverts */
|
||
|
*sendbuf = SLPBufferRealloc(*sendbuf, 4096);
|
||
|
if (*sendbuf == 0)
|
||
|
{
|
||
|
return SLP_ERROR_INTERNAL_ERROR;
|
||
|
}
|
||
|
|
||
|
if (errorcode == 0)
|
||
|
{
|
||
|
/* Note: The weird *sendbuf code is making a single SLPBuffer */
|
||
|
/* that contains multiple DAAdverts. This is a special */
|
||
|
/* process that only happens for the DA SrvRqst through */
|
||
|
/* loopback to the SLPAPI */
|
||
|
|
||
|
eh = SLPDKnownDAEnumStart();
|
||
|
if (eh)
|
||
|
{
|
||
|
while (1)
|
||
|
{
|
||
|
if (SLPDKnownDAEnum(eh, &msg, &tmp) == 0)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (((*sendbuf)->curpos) + (tmp->end - tmp->start) > (*sendbuf)->end)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* TRICKY: fix up the xid */
|
||
|
tmp->curpos = tmp->start + 10;
|
||
|
ToUINT16(tmp->curpos, message->header.xid);
|
||
|
|
||
|
memcpy((*sendbuf)->curpos, tmp->start, tmp->end - tmp->start);
|
||
|
(*sendbuf)->curpos = ((*sendbuf)->curpos) + (tmp->end - tmp->start);
|
||
|
}
|
||
|
|
||
|
SLPDKnownDAEnumEnd(eh);
|
||
|
}
|
||
|
|
||
|
/* Tack on a "terminator" DAAdvert */
|
||
|
SLPDKnownDAGenerateMyDAAdvert(SLP_ERROR_INTERNAL_ERROR,
|
||
|
0,
|
||
|
message->header.xid,
|
||
|
&tmp);
|
||
|
if (((*sendbuf)->curpos) + (tmp->end - tmp->start) <= (*sendbuf)->end)
|
||
|
{
|
||
|
memcpy((*sendbuf)->curpos, tmp->start, tmp->end - tmp->start);
|
||
|
(*sendbuf)->curpos = ((*sendbuf)->curpos) + (tmp->end - tmp->start);
|
||
|
}
|
||
|
|
||
|
/* mark the end of the sendbuf */
|
||
|
(*sendbuf)->end = (*sendbuf)->curpos;
|
||
|
|
||
|
if (tmp)
|
||
|
{
|
||
|
SLPBufferFree(tmp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errorcode;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*---------------------------------------------------------------------*/
|
||
|
/* Normal case where a remote Agent asks for a DA */
|
||
|
/*---------------------------------------------------------------------*/
|
||
|
*sendbuf = SLPBufferRealloc(*sendbuf, SLP_MAX_DATAGRAM_SIZE);
|
||
|
if (*sendbuf == 0)
|
||
|
{
|
||
|
return SLP_ERROR_INTERNAL_ERROR;
|
||
|
}
|
||
|
if (G_SlpdProperty.isDA)
|
||
|
{
|
||
|
if (message->body.srvrqst.scopelistlen == 0 ||
|
||
|
SLPIntersectStringList(message->body.srvrqst.scopelistlen,
|
||
|
message->body.srvrqst.scopelist,
|
||
|
G_SlpdProperty.useScopesLen,
|
||
|
G_SlpdProperty.useScopes))
|
||
|
{
|
||
|
errorcode = SLPDKnownDAGenerateMyDAAdvert(errorcode,
|
||
|
0,
|
||
|
message->header.xid,
|
||
|
sendbuf);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
errorcode = SLP_ERROR_MESSAGE_NOT_SUPPORTED;
|
||
|
}
|
||
|
|
||
|
/*-----------------------------------------------*/
|
||
|
/* don't return errorcodes to multicast messages */
|
||
|
/*-----------------------------------------------*/
|
||
|
if (errorcode != 0)
|
||
|
{
|
||
|
if (message->header.flags & SLP_FLAG_MCAST ||
|
||
|
ISMCAST(message->peer.sin_addr))
|
||
|
{
|
||
|
(*sendbuf)->end = (*sendbuf)->start;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errorcode;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
int ProcessSrvRqst(SLPMessage message,
|
||
|
SLPBuffer* sendbuf,
|
||
|
int errorcode)
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
{
|
||
|
int i;
|
||
|
SLPUrlEntry* urlentry;
|
||
|
SLPDDatabaseSrvRqstResult* db = 0;
|
||
|
int size = 0;
|
||
|
SLPBuffer result = *sendbuf;
|
||
|
|
||
|
#ifdef ENABLE_SLPv2_SECURITY
|
||
|
SLPAuthBlock* authblock = 0;
|
||
|
int j;
|
||
|
#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.srvrqst.prlistlen,
|
||
|
message->body.srvrqst.prlist,
|
||
|
G_SlpdProperty.interfacesLen,
|
||
|
G_SlpdProperty.interfaces) )
|
||
|
{
|
||
|
/* silently ignore */
|
||
|
result->end = result->start;
|
||
|
goto FINISHED;
|
||
|
}
|
||
|
|
||
|
/*------------------------------------------------------------------*/
|
||
|
/* 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 (SLPSpiCanVerify(G_SlpdSpiHandle,
|
||
|
message->body.srvrqst.spistrlen,
|
||
|
message->body.srvrqst.spistr) == 0)
|
||
|
{
|
||
|
errorcode = SLP_ERROR_AUTHENTICATION_UNKNOWN;
|
||
|
goto RESPOND;
|
||
|
}
|
||
|
}
|
||
|
else if (message->body.srvrqst.spistrlen)
|
||
|
{
|
||
|
errorcode = SLP_ERROR_AUTHENTICATION_UNKNOWN;
|
||
|
goto RESPOND;
|
||
|
}
|
||
|
#else
|
||
|
if (message->body.srvrqst.spistrlen)
|
||
|
{
|
||
|
errorcode = SLP_ERROR_AUTHENTICATION_UNKNOWN;
|
||
|
goto RESPOND;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/*------------------------------------------------*/
|
||
|
/* Check to to see if a this is a special SrvRqst */
|
||
|
/*------------------------------------------------*/
|
||
|
if (SLPCompareString(message->body.srvrqst.srvtypelen,
|
||
|
message->body.srvrqst.srvtype,
|
||
|
23,
|
||
|
SLP_DA_SERVICE_TYPE) == 0)
|
||
|
{
|
||
|
errorcode = ProcessDASrvRqst(message, sendbuf, errorcode);
|
||
|
if (errorcode == 0)
|
||
|
{
|
||
|
// Since we have an errorcode of 0, we were successful,
|
||
|
// and have already formed a response packet; return now.
|
||
|
return errorcode;
|
||
|
}
|
||
|
|
||
|
goto RESPOND;
|
||
|
|
||
|
}
|
||
|
if (SLPCompareString(message->body.srvrqst.srvtypelen,
|
||
|
message->body.srvrqst.srvtype,
|
||
|
21,
|
||
|
SLP_SA_SERVICE_TYPE) == 0)
|
||
|
{
|
||
|
errorcode = ProcessSASrvRqst(message, sendbuf, errorcode);
|
||
|
if (errorcode == 0)
|
||
|
{
|
||
|
// Since we have an errorcode of 0, we were successful,
|
||
|
// and have already formed a response packet; return now.
|
||
|
return errorcode;
|
||
|
}
|
||
|
|
||
|
goto RESPOND;
|
||
|
}
|
||
|
|
||
|
/*------------------------------------*/
|
||
|
/* Make sure that we handle the scope */
|
||
|
/*------ -----------------------------*/
|
||
|
if (SLPIntersectStringList(message->body.srvrqst.scopelistlen,
|
||
|
message->body.srvrqst.scopelist,
|
||
|
G_SlpdProperty.useScopesLen,
|
||
|
G_SlpdProperty.useScopes) != 0)
|
||
|
{
|
||
|
/*-------------------------------*/
|
||
|
/* Find services in the database */
|
||
|
/*-------------------------------*/
|
||
|
errorcode = SLPDDatabaseSrvRqstStart(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->urlcount == 0)
|
||
|
{
|
||
|
if (message->header.flags & SLP_FLAG_MCAST ||
|
||
|
ISMCAST(message->peer.sin_addr))
|
||
|
{
|
||
|
result->end = result->start;
|
||
|
goto FINISHED;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*-------------------------------------------------------------*/
|
||
|
/* ensure the buffer is big enough to handle the whole srvrply */
|
||
|
/*-------------------------------------------------------------*/
|
||
|
size = message->header.langtaglen + 18; /* 14 bytes for header */
|
||
|
/* 2 bytes for error code */
|
||
|
/* 2 bytes for url count */
|
||
|
if (errorcode == 0)
|
||
|
{
|
||
|
for (i=0;i<db->urlcount;i++)
|
||
|
{
|
||
|
/* urlentry is the url from the db result */
|
||
|
urlentry = db->urlarray[i];
|
||
|
|
||
|
size += urlentry->urllen + 6; /* 1 byte for reserved */
|
||
|
/* 2 bytes for lifetime */
|
||
|
/* 2 bytes for urllen */
|
||
|
/* 1 byte for authcount */
|
||
|
#ifdef ENABLE_SLPv2_SECURITY
|
||
|
|
||
|
/* make room to include the authblock that was asked for */
|
||
|
if (G_SlpdProperty.securityEnabled &&
|
||
|
message->body.srvrqst.spistrlen )
|
||
|
{
|
||
|
for (j=0; j<urlentry->authcount;j++)
|
||
|
{
|
||
|
if (SLPCompareString(urlentry->autharray[j].spistrlen,
|
||
|
urlentry->autharray[j].spistr,
|
||
|
message->body.srvrqst.spistrlen,
|
||
|
message->body.srvrqst.spistr) == 0)
|
||
|
{
|
||
|
authblock = &(urlentry->autharray[j]);
|
||
|
size += authblock->length;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*------------------------------*/
|
||
|
/* Reallocate the result buffer */
|
||
|
/*------------------------------*/
|
||
|
result = SLPBufferRealloc(result,size);
|
||
|
if (result == 0)
|
||
|
{
|
||
|
errorcode = SLP_ERROR_INTERNAL_ERROR;
|
||
|
goto FINISHED;
|
||
|
}
|
||
|
|
||
|
/*----------------*/
|
||
|
/* Add the header */
|
||
|
/*----------------*/
|
||
|
/*version*/
|
||
|
*(result->start) = 2;
|
||
|
/*function id*/
|
||
|
*(result->start + 1) = SLP_FUNCT_SRVRPLY;
|
||
|
/*length*/
|
||
|
ToUINT24(result->start + 2, size);
|
||
|
/*flags*/
|
||
|
ToUINT16(result->start + 5,
|
||
|
(size > SLP_MAX_DATAGRAM_SIZE ? SLP_FLAG_OVERFLOW : 0));
|
||
|
/*ext offset*/
|
||
|
ToUINT24(result->start + 7,0);
|
||
|
/*xid*/
|
||
|
ToUINT16(result->start + 10,message->header.xid);
|
||
|
/*lang tag len*/
|
||
|
ToUINT16(result->start + 12,message->header.langtaglen);
|
||
|
/*lang tag*/
|
||
|
memcpy(result->start + 14,
|
||
|
message->header.langtag,
|
||
|
message->header.langtaglen);
|
||
|
|
||
|
/*-------------------------*/
|
||
|
/* Add rest of the SrvRply */
|
||
|
/*-------------------------*/
|
||
|
result->curpos = result->start + 14 + message->header.langtaglen;
|
||
|
/* error code*/
|
||
|
ToUINT16(result->curpos, errorcode);
|
||
|
result->curpos = result->curpos + 2;
|
||
|
if (errorcode == 0)
|
||
|
{
|
||
|
/* urlentry count */
|
||
|
ToUINT16(result->curpos, db->urlcount);
|
||
|
result->curpos = result->curpos + 2;
|
||
|
|
||
|
for (i=0;i<db->urlcount;i++)
|
||
|
{
|
||
|
/* urlentry is the url from the db result */
|
||
|
urlentry = db->urlarray[i];
|
||
|
|
||
|
#ifdef ENABLE_SLPv1
|
||
|
if (urlentry->opaque == 0)
|
||
|
{
|
||
|
/* url-entry reserved */
|
||
|
*result->curpos = 0;
|
||
|
result->curpos = result->curpos + 1;
|
||
|
/* url-entry lifetime */
|
||
|
ToUINT16(result->curpos,urlentry->lifetime);
|
||
|
result->curpos = result->curpos + 2;
|
||
|
/* url-entry urllen */
|
||
|
ToUINT16(result->curpos,urlentry->urllen);
|
||
|
result->curpos = result->curpos + 2;
|
||
|
/* url-entry url */
|
||
|
memcpy(result->curpos,urlentry->url,urlentry->urllen);
|
||
|
result->curpos = result->curpos + urlentry->urllen;
|
||
|
/* url-entry auths */
|
||
|
*result->curpos = 0;
|
||
|
result->curpos = result->curpos + 1;
|
||
|
}
|
||
|
else
|
||
|
#endif
|
||
|
{
|
||
|
/* Use an opaque copy if available (and authentication is not being used)*/
|
||
|
/* TRICKY: fix up the lifetime */
|
||
|
ToUINT16(urlentry->opaque + 1,urlentry->lifetime);
|
||
|
memcpy(result->curpos,urlentry->opaque,urlentry->opaquelen);
|
||
|
result->curpos = result->curpos + urlentry->opaquelen;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* set urlentry count to 0*/
|
||
|
ToUINT16(result->curpos, 0);
|
||
|
result->curpos = result->curpos + 2;
|
||
|
}
|
||
|
|
||
|
FINISHED:
|
||
|
if (db) SLPDDatabaseSrvRqstEnd(db);
|
||
|
|
||
|
*sendbuf = result;
|
||
|
|
||
|
return errorcode;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
int ProcessSrvReg(SLPMessage message,
|
||
|
SLPBuffer recvbuf,
|
||
|
SLPBuffer* sendbuf,
|
||
|
int errorcode)
|
||
|
/* */
|
||
|
/* Returns: non-zero if message should be silently dropped */
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
{
|
||
|
SLPBuffer result = *sendbuf;
|
||
|
|
||
|
/*--------------------------------------------------------------*/
|
||
|
/* If errorcode is set, we can not be sure that message is good */
|
||
|
/* Go directly to send response code also do not process mcast */
|
||
|
/* srvreg or srvdereg messages */
|
||
|
/*--------------------------------------------------------------*/
|
||
|
if (errorcode ||
|
||
|
message->header.flags & SLP_FLAG_MCAST ||
|
||
|
ISMCAST(message->peer.sin_addr))
|
||
|
{
|
||
|
goto RESPOND;
|
||
|
}
|
||
|
|
||
|
/*------------------------------------*/
|
||
|
/* Make sure that we handle the scope */
|
||
|
/*------ -----------------------------*/
|
||
|
if (SLPIntersectStringList(message->body.srvreg.scopelistlen,
|
||
|
message->body.srvreg.scopelist,
|
||
|
G_SlpdProperty.useScopesLen,
|
||
|
G_SlpdProperty.useScopes))
|
||
|
{
|
||
|
|
||
|
#ifdef ENABLE_SLPv2_SECURITY
|
||
|
|
||
|
/*-------------------------------*/
|
||
|
/* Validate the authblocks */
|
||
|
/*-------------------------------*/
|
||
|
errorcode = SLPAuthVerifyUrl(G_SlpdSpiHandle,
|
||
|
0,
|
||
|
&(message->body.srvreg.urlentry));
|
||
|
if (errorcode == 0)
|
||
|
{
|
||
|
errorcode = SLPAuthVerifyString(G_SlpdSpiHandle,
|
||
|
0,
|
||
|
message->body.srvreg.attrlistlen,
|
||
|
message->body.srvreg.attrlist,
|
||
|
message->body.srvreg.authcount,
|
||
|
message->body.srvreg.autharray);
|
||
|
}
|
||
|
if (errorcode == 0)
|
||
|
#endif
|
||
|
{
|
||
|
/*--------------------------------------------------------------*/
|
||
|
/* Put the registration in the */
|
||
|
/*--------------------------------------------------------------*/
|
||
|
/* TRICKY: Remember the recvbuf was duplicated back in */
|
||
|
/* SLPDProcessMessage() */
|
||
|
|
||
|
if (ISLOCAL(message->peer.sin_addr))
|
||
|
{
|
||
|
message->body.srvreg.source= SLP_REG_SOURCE_LOCAL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
message->body.srvreg.source = SLP_REG_SOURCE_REMOTE;
|
||
|
}
|
||
|
|
||
|
errorcode = SLPDDatabaseReg(message, recvbuf);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;
|
||
|
}
|
||
|
|
||
|
RESPOND:
|
||
|
/*--------------------------------------------------------------------*/
|
||
|
/* don't send back reply anything multicast SrvReg (set result empty) */
|
||
|
/*--------------------------------------------------------------------*/
|
||
|
if (message->header.flags & SLP_FLAG_MCAST ||
|
||
|
ISMCAST(message->peer.sin_addr))
|
||
|
{
|
||
|
result->end = result->start;
|
||
|
goto FINISHED;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*------------------------------------------------------------*/
|
||
|
/* ensure the buffer is big enough to handle the whole srvack */
|
||
|
/*------------------------------------------------------------*/
|
||
|
result = SLPBufferRealloc(result,message->header.langtaglen + 16);
|
||
|
if (result == 0)
|
||
|
{
|
||
|
errorcode = SLP_ERROR_INTERNAL_ERROR;
|
||
|
goto FINISHED;
|
||
|
}
|
||
|
|
||
|
/*----------------*/
|
||
|
/* Add the header */
|
||
|
/*----------------*/
|
||
|
/*version*/
|
||
|
*(result->start) = 2;
|
||
|
/*function id*/
|
||
|
*(result->start + 1) = SLP_FUNCT_SRVACK;
|
||
|
/*length*/
|
||
|
ToUINT24(result->start + 2,message->header.langtaglen + 16);
|
||
|
/*flags*/
|
||
|
ToUINT16(result->start + 5,0);
|
||
|
/*ext offset*/
|
||
|
ToUINT24(result->start + 7,0);
|
||
|
/*xid*/
|
||
|
ToUINT16(result->start + 10,message->header.xid);
|
||
|
/*lang tag len*/
|
||
|
ToUINT16(result->start + 12,message->header.langtaglen);
|
||
|
/*lang tag*/
|
||
|
memcpy(result->start + 14,
|
||
|
message->header.langtag,
|
||
|
message->header.langtaglen);
|
||
|
|
||
|
/*-------------------*/
|
||
|
/* Add the errorcode */
|
||
|
/*-------------------*/
|
||
|
ToUINT16(result->start + 14 + message->header.langtaglen, errorcode);
|
||
|
|
||
|
FINISHED:
|
||
|
*sendbuf = result;
|
||
|
return errorcode;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
int ProcessSrvDeReg(SLPMessage message,
|
||
|
SLPBuffer* sendbuf,
|
||
|
int errorcode)
|
||
|
/* */
|
||
|
/* Returns: non-zero if message should be silently dropped */
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
{
|
||
|
SLPBuffer result = *sendbuf;
|
||
|
|
||
|
/*--------------------------------------------------------------*/
|
||
|
/* If errorcode is set, we can not be sure that message is good */
|
||
|
/* Go directly to send response code also do not process mcast */
|
||
|
/* srvreg or srvdereg messages */
|
||
|
/*--------------------------------------------------------------*/
|
||
|
if (errorcode || message->header.flags & SLP_FLAG_MCAST)
|
||
|
{
|
||
|
goto RESPOND;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*------------------------------------*/
|
||
|
/* Make sure that we handle the scope */
|
||
|
/*------------------------------------*/
|
||
|
if (SLPIntersectStringList(message->body.srvdereg.scopelistlen,
|
||
|
message->body.srvdereg.scopelist,
|
||
|
G_SlpdProperty.useScopesLen,
|
||
|
G_SlpdProperty.useScopes))
|
||
|
{
|
||
|
#ifdef ENABLE_SLPv2_SECURITY
|
||
|
|
||
|
/*-------------------------------*/
|
||
|
/* Validate the authblocks */
|
||
|
/*-------------------------------*/
|
||
|
errorcode = SLPAuthVerifyUrl(G_SlpdSpiHandle,
|
||
|
0,
|
||
|
&(message->body.srvdereg.urlentry));
|
||
|
if (errorcode == 0)
|
||
|
#endif
|
||
|
{
|
||
|
/*--------------------------------------*/
|
||
|
/* remove the service from the database */
|
||
|
/*--------------------------------------*/
|
||
|
errorcode = SLPDDatabaseDeReg(message);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;
|
||
|
}
|
||
|
|
||
|
RESPOND:
|
||
|
/*---------------------------------------------------------*/
|
||
|
/* don't do anything multicast SrvDeReg (set result empty) */
|
||
|
/*---------------------------------------------------------*/
|
||
|
if (message->header.flags & SLP_FLAG_MCAST ||
|
||
|
ISMCAST(message->peer.sin_addr))
|
||
|
{
|
||
|
result->end = result->start;
|
||
|
goto FINISHED;
|
||
|
}
|
||
|
|
||
|
/*------------------------------------------------------------*/
|
||
|
/* ensure the buffer is big enough to handle the whole srvack */
|
||
|
/*------------------------------------------------------------*/
|
||
|
result = SLPBufferRealloc(result,message->header.langtaglen + 16);
|
||
|
if (result == 0)
|
||
|
{
|
||
|
errorcode = SLP_ERROR_INTERNAL_ERROR;
|
||
|
goto FINISHED;
|
||
|
}
|
||
|
|
||
|
/*----------------*/
|
||
|
/* Add the header */
|
||
|
/*----------------*/
|
||
|
/*version*/
|
||
|
*(result->start) = 2;
|
||
|
/*function id*/
|
||
|
*(result->start + 1) = SLP_FUNCT_SRVACK;
|
||
|
/*length*/
|
||
|
ToUINT24(result->start + 2,message->header.langtaglen + 16);
|
||
|
/*flags*/
|
||
|
ToUINT16(result->start + 5,0);
|
||
|
/*ext offset*/
|
||
|
ToUINT24(result->start + 7,0);
|
||
|
/*xid*/
|
||
|
ToUINT16(result->start + 10,message->header.xid);
|
||
|
/*lang tag len*/
|
||
|
ToUINT16(result->start + 12,message->header.langtaglen);
|
||
|
/*lang tag*/
|
||
|
memcpy(result->start + 14,
|
||
|
message->header.langtag,
|
||
|
message->header.langtaglen);
|
||
|
|
||
|
/*-------------------*/
|
||
|
/* Add the errorcode */
|
||
|
/*-------------------*/
|
||
|
ToUINT16(result->start + 14 + message->header.langtaglen, errorcode);
|
||
|
|
||
|
FINISHED:
|
||
|
*sendbuf = result;
|
||
|
return errorcode;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
int ProcessSrvAck(SLPMessage message,
|
||
|
SLPBuffer* sendbuf,
|
||
|
int errorcode)
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
{
|
||
|
/* Ignore SrvAck. Just return errorcode to caller */
|
||
|
SLPBuffer result = *sendbuf;
|
||
|
|
||
|
result->end = result->start;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
int ProcessAttrRqst(SLPMessage message,
|
||
|
SLPBuffer* sendbuf,
|
||
|
int errorcode)
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
{
|
||
|
SLPDDatabaseAttrRqstResult* db = 0;
|
||
|
int size = 0;
|
||
|
SLPBuffer result = *sendbuf;
|
||
|
|
||
|
#ifdef ENABLE_SLPv2_SECURITY
|
||
|
int i;
|
||
|
unsigned char* generatedauth = 0;
|
||
|
int generatedauthlen = 0;
|
||
|
unsigned char* 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 ||
|
||
|
ISMCAST(message->peer.sin_addr))
|
||
|
{
|
||
|
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->start) = 2;
|
||
|
/*function id*/
|
||
|
*(result->start + 1) = SLP_FUNCT_ATTRRPLY;
|
||
|
/*length*/
|
||
|
ToUINT24(result->start + 2,size);
|
||
|
/*flags*/
|
||
|
ToUINT16(result->start + 5,
|
||
|
(size > SLP_MAX_DATAGRAM_SIZE ? SLP_FLAG_OVERFLOW : 0));
|
||
|
/*ext offset*/
|
||
|
ToUINT24(result->start + 7,0);
|
||
|
/*xid*/
|
||
|
ToUINT16(result->start + 10,message->header.xid);
|
||
|
/*lang tag len*/
|
||
|
ToUINT16(result->start + 12,message->header.langtaglen);
|
||
|
/*lang tag*/
|
||
|
memcpy(result->start + 14,
|
||
|
message->header.langtag,
|
||
|
message->header.langtaglen);
|
||
|
|
||
|
/*--------------------------*/
|
||
|
/* Add rest of the AttrRqst */
|
||
|
/*--------------------------*/
|
||
|
result->curpos = result->start + 14 + message->header.langtaglen;
|
||
|
/* error code*/
|
||
|
ToUINT16(result->curpos, errorcode);
|
||
|
result->curpos = result->curpos + 2;
|
||
|
if (errorcode == 0)
|
||
|
{
|
||
|
/* attr-list len */
|
||
|
ToUINT16(result->curpos, db->attrlistlen);
|
||
|
result->curpos = result->curpos + 2;
|
||
|
if (db->attrlistlen)
|
||
|
{
|
||
|
memcpy(result->curpos, db->attrlist, db->attrlistlen);
|
||
|
}
|
||
|
result->curpos = result->curpos + db->attrlistlen;
|
||
|
|
||
|
/* authentication block */
|
||
|
#ifdef ENABLE_SLPv2_SECURITY
|
||
|
if (opaqueauth)
|
||
|
{
|
||
|
/* authcount */
|
||
|
*(result->curpos) = 1;
|
||
|
result->curpos = result->curpos + 1;
|
||
|
memcpy(result->curpos,
|
||
|
opaqueauth,
|
||
|
opaqueauthlen);
|
||
|
result->curpos = result->curpos + opaqueauthlen;
|
||
|
}
|
||
|
else
|
||
|
#endif
|
||
|
{
|
||
|
/* authcount */
|
||
|
*(result->curpos) = 0;
|
||
|
result->curpos = result->curpos + 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
FINISHED:
|
||
|
|
||
|
#ifdef ENABLE_SLPv2_SECURITY
|
||
|
/* free the generated authblock if any */
|
||
|
if (generatedauth) xfree(generatedauth);
|
||
|
#endif
|
||
|
|
||
|
if (db) SLPDDatabaseAttrRqstEnd(db);
|
||
|
|
||
|
*sendbuf = result;
|
||
|
|
||
|
return errorcode;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
int ProcessDAAdvert(SLPMessage message,
|
||
|
SLPBuffer recvbuf,
|
||
|
SLPBuffer* sendbuf,
|
||
|
int errorcode)
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
{
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
/*--------------------------------------------------------------*/
|
||
|
/* If net.slp.passiveDADetection is turned off then we ignore */
|
||
|
/* DAAdverts with xid == 0 */
|
||
|
/*--------------------------------------------------------------*/
|
||
|
if(G_SlpdProperty.passiveDADetection == 0 &&
|
||
|
message->header.xid == 0)
|
||
|
{
|
||
|
goto RESPOND;
|
||
|
}
|
||
|
|
||
|
/*--------------------------------------------------------------*/
|
||
|
/* If net.slp.DAActiveDiscoveryInterval == 0 then we ignore */
|
||
|
/* DAAdverts with xid != 0 */
|
||
|
/*--------------------------------------------------------------*/
|
||
|
if(G_SlpdProperty.DAActiveDiscoveryInterval == 0 &&
|
||
|
message->header.xid != 0)
|
||
|
{
|
||
|
goto RESPOND;
|
||
|
}
|
||
|
|
||
|
/*-------------------------------*/
|
||
|
/* Validate the authblocks */
|
||
|
/*-------------------------------*/
|
||
|
#ifdef ENABLE_SLPv2_SECURITY
|
||
|
errorcode = SLPAuthVerifyDAAdvert(G_SlpdSpiHandle,
|
||
|
0,
|
||
|
&(message->body.daadvert));
|
||
|
if (errorcode == 0);
|
||
|
#endif
|
||
|
{
|
||
|
/* Only process if errorcode is not set */
|
||
|
if (message->body.daadvert.errorcode == SLP_ERROR_OK)
|
||
|
{
|
||
|
errorcode = SLPDKnownDAAdd(message,recvbuf);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RESPOND:
|
||
|
/* DAAdverts should never be replied to. Set result buffer to empty*/
|
||
|
result->end = result->start;
|
||
|
|
||
|
*sendbuf = result;
|
||
|
|
||
|
return errorcode;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
int ProcessSrvTypeRqst(SLPMessage message,
|
||
|
SLPBuffer* sendbuf,
|
||
|
int errorcode)
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
{
|
||
|
int size = 0;
|
||
|
SLPDDatabaseSrvTypeRqstResult* db = 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.srvtyperqst.prlistlen,
|
||
|
message->body.srvtyperqst.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.srvtyperqst.scopelistlen,
|
||
|
message->body.srvtyperqst.scopelist,
|
||
|
G_SlpdProperty.useScopesLen,
|
||
|
G_SlpdProperty.useScopes) != 0)
|
||
|
{
|
||
|
/*------------------------------------*/
|
||
|
/* Find service types in the database */
|
||
|
/*------------------------------------*/
|
||
|
errorcode = SLPDDatabaseSrvTypeRqstStart(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->srvtypelistlen == 0)
|
||
|
{
|
||
|
if (message->header.flags & SLP_FLAG_MCAST ||
|
||
|
ISMCAST(message->peer.sin_addr))
|
||
|
{
|
||
|
result->end = result->start;
|
||
|
goto FINISHED;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*-----------------------------------------------------------------*/
|
||
|
/* ensure the buffer is big enough to handle the whole srvtyperply */
|
||
|
/*-----------------------------------------------------------------*/
|
||
|
size = message->header.langtaglen + 18; /* 14 bytes for header */
|
||
|
/* 2 bytes for error code */
|
||
|
/* 2 bytes for srvtype
|
||
|
list length */
|
||
|
if(errorcode == 0)
|
||
|
{
|
||
|
size += db->srvtypelistlen;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*------------------------------*/
|
||
|
/* Reallocate the result buffer */
|
||
|
/*------------------------------*/
|
||
|
result = SLPBufferRealloc(result,size);
|
||
|
if (result == 0)
|
||
|
{
|
||
|
errorcode = SLP_ERROR_INTERNAL_ERROR;
|
||
|
goto FINISHED;
|
||
|
}
|
||
|
|
||
|
/*----------------*/
|
||
|
/* Add the header */
|
||
|
/*----------------*/
|
||
|
/*version*/
|
||
|
*(result->start) = 2;
|
||
|
/*function id*/
|
||
|
*(result->start + 1) = SLP_FUNCT_SRVTYPERPLY;
|
||
|
/*length*/
|
||
|
ToUINT24(result->start + 2,size);
|
||
|
/*flags*/
|
||
|
ToUINT16(result->start + 5,
|
||
|
(size > SLP_MAX_DATAGRAM_SIZE ? SLP_FLAG_OVERFLOW : 0));
|
||
|
/*ext offset*/
|
||
|
ToUINT24(result->start + 7,0);
|
||
|
/*xid*/
|
||
|
ToUINT16(result->start + 10,message->header.xid);
|
||
|
/*lang tag len*/
|
||
|
ToUINT16(result->start + 12,message->header.langtaglen);
|
||
|
/*lang tag*/
|
||
|
memcpy(result->start + 14,
|
||
|
message->header.langtag,
|
||
|
message->header.langtaglen);
|
||
|
|
||
|
/*-----------------------------*/
|
||
|
/* Add rest of the SrvTypeRply */
|
||
|
/*-----------------------------*/
|
||
|
result->curpos = result->start + 14 + message->header.langtaglen;
|
||
|
|
||
|
/* error code*/
|
||
|
ToUINT16(result->curpos, errorcode);
|
||
|
result->curpos += 2;
|
||
|
|
||
|
if (errorcode == 0)
|
||
|
{
|
||
|
/* length of srvtype-list */
|
||
|
ToUINT16(result->curpos, db->srvtypelistlen);
|
||
|
result->curpos += 2;
|
||
|
memcpy(result->curpos,
|
||
|
db->srvtypelist,
|
||
|
db->srvtypelistlen);
|
||
|
result->curpos += db->srvtypelistlen;
|
||
|
}
|
||
|
|
||
|
|
||
|
FINISHED:
|
||
|
if (db) SLPDDatabaseSrvTypeRqstEnd(db);
|
||
|
|
||
|
*sendbuf = result;
|
||
|
|
||
|
return errorcode;
|
||
|
}
|
||
|
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
int ProcessSAAdvert(SLPMessage message,
|
||
|
SLPBuffer* sendbuf,
|
||
|
int errorcode)
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
{
|
||
|
/* Ignore all SAADVERTS */
|
||
|
(*sendbuf)->end = (*sendbuf)->start;
|
||
|
return errorcode;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*=========================================================================*/
|
||
|
int SLPDProcessMessage(struct sockaddr_in* peerinfo,
|
||
|
SLPBuffer recvbuf,
|
||
|
SLPBuffer* sendbuf)
|
||
|
/* Processes the recvbuf and places the results in sendbuf */
|
||
|
/* */
|
||
|
/* peerinfo - the socket the message was received on */
|
||
|
/* */
|
||
|
/* recvbuf - message to process */
|
||
|
/* */
|
||
|
/* sendbuf - results of the processed message */
|
||
|
/* */
|
||
|
/* Returns - zero on success if sendbuf contains a response to send. */
|
||
|
/* non-zero if sendbuf does not contain a response to send */
|
||
|
/*=========================================================================*/
|
||
|
{
|
||
|
SLPHeader header;
|
||
|
SLPMessage message = 0;
|
||
|
int errorcode = 0;
|
||
|
|
||
|
SLPDLogMessage(SLPDLOG_TRACEMSG_IN,peerinfo,recvbuf);
|
||
|
|
||
|
if(!*sendbuf)
|
||
|
{
|
||
|
*sendbuf = SLPBufferAlloc(SLP_MAX_DATAGRAM_SIZE);
|
||
|
if (!*sendbuf)
|
||
|
return SLP_ERROR_PARSE_ERROR;
|
||
|
}
|
||
|
/* set the sendbuf empty */
|
||
|
(*sendbuf)->end = (*sendbuf)->start;
|
||
|
|
||
|
/* zero out the header before parsing it */
|
||
|
memset(&header,0,sizeof(header));
|
||
|
|
||
|
/* Parse just the message header */
|
||
|
recvbuf->curpos = recvbuf->start;
|
||
|
errorcode = SLPMessageParseHeader(recvbuf,&header);
|
||
|
|
||
|
/* Reset the buffer "curpos" pointer so that full message can be
|
||
|
* parsed later
|
||
|
*/
|
||
|
recvbuf->curpos = recvbuf->start;
|
||
|
|
||
|
#if defined(ENABLE_SLPv1)
|
||
|
/* if version == 1 then parse message as a version 1 message */
|
||
|
if (errorcode == SLP_ERROR_VER_NOT_SUPPORTED &&
|
||
|
header.version == 1)
|
||
|
{
|
||
|
errorcode = SLPDv1ProcessMessage(peerinfo,
|
||
|
recvbuf,
|
||
|
sendbuf);
|
||
|
}
|
||
|
else
|
||
|
#endif
|
||
|
if (errorcode == 0)
|
||
|
{
|
||
|
/* TRICKY: Duplicate SRVREG recvbufs *before* parsing them */
|
||
|
/* we do this because we are going to keep track of */
|
||
|
/* in the registration database */
|
||
|
if (header.functionid == SLP_FUNCT_SRVREG ||
|
||
|
header.functionid == SLP_FUNCT_DAADVERT )
|
||
|
{
|
||
|
recvbuf = SLPBufferDup(recvbuf);
|
||
|
if (recvbuf == NULL)
|
||
|
{
|
||
|
return SLP_ERROR_INTERNAL_ERROR;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Allocate the message descriptor */
|
||
|
message = SLPMessageAlloc();
|
||
|
if (message)
|
||
|
{
|
||
|
/* Parse the message and fill out the message descriptor */
|
||
|
errorcode = SLPMessageParseBuffer(peerinfo,recvbuf, message);
|
||
|
if (errorcode == 0)
|
||
|
{
|
||
|
/* Process messages based on type */
|
||
|
switch (message->header.functionid)
|
||
|
{
|
||
|
case SLP_FUNCT_SRVRQST:
|
||
|
errorcode = ProcessSrvRqst(message,sendbuf,errorcode);
|
||
|
break;
|
||
|
|
||
|
case SLP_FUNCT_SRVREG:
|
||
|
errorcode = ProcessSrvReg(message,recvbuf,sendbuf,errorcode);
|
||
|
if (errorcode == 0)
|
||
|
{
|
||
|
SLPDKnownDAEcho(message, recvbuf);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case SLP_FUNCT_SRVDEREG:
|
||
|
errorcode = ProcessSrvDeReg(message,sendbuf,errorcode);
|
||
|
if (errorcode == 0)
|
||
|
{
|
||
|
SLPDKnownDAEcho(message, recvbuf);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case SLP_FUNCT_SRVACK:
|
||
|
errorcode = ProcessSrvAck(message,sendbuf, errorcode);
|
||
|
break;
|
||
|
|
||
|
case SLP_FUNCT_ATTRRQST:
|
||
|
errorcode = ProcessAttrRqst(message,sendbuf, errorcode);
|
||
|
break;
|
||
|
|
||
|
case SLP_FUNCT_DAADVERT:
|
||
|
errorcode = ProcessDAAdvert(message,
|
||
|
recvbuf,
|
||
|
sendbuf,
|
||
|
errorcode);
|
||
|
break;
|
||
|
|
||
|
case SLP_FUNCT_SRVTYPERQST:
|
||
|
errorcode = ProcessSrvTypeRqst(message, sendbuf, errorcode);
|
||
|
break;
|
||
|
|
||
|
case SLP_FUNCT_SAADVERT:
|
||
|
errorcode = ProcessSAAdvert(message, sendbuf, errorcode);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
/* Should never happen... but we're paranoid */
|
||
|
errorcode = SLP_ERROR_PARSE_ERROR;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SLPDLogParseWarning(peerinfo, recvbuf);
|
||
|
}
|
||
|
|
||
|
if (header.functionid == SLP_FUNCT_SRVREG ||
|
||
|
header.functionid == SLP_FUNCT_DAADVERT )
|
||
|
{
|
||
|
/* TRICKY: If this is a reg or daadvert message we do not
|
||
|
* free the message descriptor or duplicated recvbuf
|
||
|
* because they are being kept in the database!
|
||
|
*
|
||
|
*/
|
||
|
if (errorcode == 0)
|
||
|
{
|
||
|
goto FINISHED;
|
||
|
}
|
||
|
|
||
|
/* TRICKY: If there is an error we need to free the
|
||
|
* duplicated recvbuf,
|
||
|
*/
|
||
|
SLPBufferFree(recvbuf);
|
||
|
}
|
||
|
|
||
|
SLPMessageFree(message);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* out of memory */
|
||
|
errorcode = SLP_ERROR_INTERNAL_ERROR;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SLPDLogParseWarning(peerinfo,recvbuf);
|
||
|
}
|
||
|
|
||
|
FINISHED:
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
if (errorcode)
|
||
|
{
|
||
|
SLPDLog("\n*** DEBUG *** errorcode %i during processing of message from %s\n",
|
||
|
errorcode,
|
||
|
inet_ntoa(peerinfo->sin_addr));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/* Log message silently ignored because of an error */
|
||
|
if(errorcode)
|
||
|
{
|
||
|
if (*sendbuf == 0 ||
|
||
|
(*sendbuf)->end == (*sendbuf)->start )
|
||
|
{
|
||
|
SLPDLogMessage(SLPDLOG_TRACEDROP,peerinfo,recvbuf);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Log trace message */
|
||
|
SLPDLogMessage(SLPDLOG_TRACEMSG_OUT, peerinfo, *sendbuf);
|
||
|
|
||
|
return errorcode;
|
||
|
}
|