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.
1213 lines
39 KiB
1213 lines
39 KiB
/***************************************************************************/
|
|
/* */
|
|
/* Project: OpenSLP - OpenSource implementation of Service Location */
|
|
/* Protocol */
|
|
/* */
|
|
/* File: slp_message.h */
|
|
/* */
|
|
/* Abstract: Header file that defines structures and constants that are */
|
|
/* specific to the SLP wire protocol 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. */
|
|
/* */
|
|
/***************************************************************************/
|
|
|
|
#include "slp_message.h"
|
|
#include "slp_xmalloc.h"
|
|
|
|
#ifndef _WIN32
|
|
#include <sys/types.h>
|
|
#include <netinet/in.h>
|
|
#endif
|
|
|
|
#if defined(ENABLE_SLPv1)
|
|
#include <slp_v1message.h>
|
|
#endif
|
|
|
|
/*=========================================================================*/
|
|
int SLPMessageParseHeader(SLPBuffer buffer, SLPHeader* header)
|
|
/* Fill out a header structure with what ever is in the buffer */
|
|
/* */
|
|
/* buffer (IN) the buffer to be parsed */
|
|
/* */
|
|
/* header (IN/OUT) pointer to the header structure to fill out */
|
|
/*=========================================================================*/
|
|
{
|
|
if (buffer->end - buffer->start < 2)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
header->version = *(buffer->curpos);
|
|
header->functionid = *(buffer->curpos + 1);
|
|
|
|
if(header->version != 2)
|
|
{
|
|
return SLP_ERROR_VER_NOT_SUPPORTED;
|
|
}
|
|
/* check for invalid length 18 bytes is the smallest v2 message*/
|
|
if (buffer->end - buffer->start < 18)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
header->length = AsUINT24(buffer->curpos + 2);
|
|
header->flags = AsUINT16(buffer->curpos + 5);
|
|
header->encoding = 0; /* not used for SLPv2 */
|
|
header->extoffset = AsUINT24(buffer->curpos + 7);
|
|
header->xid = AsUINT16(buffer->curpos + 10);
|
|
header->langtaglen = AsUINT16(buffer->curpos + 12);
|
|
header->langtag = buffer->curpos + 14;
|
|
|
|
/* check for invalid function id */
|
|
if(header->functionid > SLP_FUNCT_SAADVERT)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
|
|
if(header->length != buffer->end - buffer->start)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
|
|
/* check for invalid flags */
|
|
if(header->flags & 0x1fff)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
buffer->curpos = buffer->curpos + header->langtaglen + 14;
|
|
|
|
/* check for invalid langtaglen */
|
|
if((void*)(header->langtag + header->langtaglen) > (void*)buffer->end)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
|
|
/* check for invalid ext offset */
|
|
if(buffer->start + header->extoffset > buffer->end)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int ParseAuthBlock(SLPBuffer buffer, SLPAuthBlock* authblock)
|
|
/* Returns - Zero on success, SLP_ERROR_INTERNAL_ERROR (out of memory) or */
|
|
/* SLP_ERROR_PARSE_ERROR. */
|
|
/*--------------------------------------------------------------------------*/
|
|
{
|
|
/* make sure that min size is met */
|
|
if(buffer->end - buffer->curpos < 10)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
|
|
authblock->opaque = buffer->curpos;
|
|
|
|
authblock->bsd = AsUINT16(buffer->curpos);
|
|
authblock->length = AsUINT16(buffer->curpos + 2);
|
|
|
|
if(authblock->length > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
|
|
authblock->timestamp = AsUINT32(buffer->curpos + 4);
|
|
authblock->spistrlen = AsUINT16(buffer->curpos + 8);
|
|
authblock->spistr = buffer->curpos + 10;
|
|
|
|
if(authblock->spistrlen > buffer->end - buffer->curpos + 10)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
|
|
authblock->authstruct = buffer->curpos + authblock->spistrlen + 10;
|
|
|
|
authblock->opaquelen = authblock->length;
|
|
|
|
buffer->curpos = buffer->curpos + authblock->length;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int ParseUrlEntry(SLPBuffer buffer, SLPUrlEntry* urlentry)
|
|
/* */
|
|
/* Returns - Zero on success, SLP_ERROR_INTERNAL_ERROR (out of memory) or */
|
|
/* SLP_ERROR_PARSE_ERROR. */
|
|
/*--------------------------------------------------------------------------*/
|
|
{
|
|
int result;
|
|
int i;
|
|
|
|
/* make sure that min size is met */
|
|
if(buffer->end - buffer->curpos < 6)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
|
|
urlentry->opaque = buffer->curpos;
|
|
|
|
/* parse out reserved */
|
|
urlentry->reserved = *(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 1;
|
|
|
|
/* parse out lifetime */
|
|
urlentry->lifetime = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
|
|
/* parse out url */
|
|
urlentry->urllen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(urlentry->urllen + 1 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
|
|
urlentry->url = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + urlentry->urllen;
|
|
|
|
/* parse out auth block count */
|
|
urlentry->authcount = *(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 1;
|
|
|
|
/* parse out the auth block (if any) */
|
|
if(urlentry->authcount)
|
|
{
|
|
urlentry->autharray = (SLPAuthBlock*)xmalloc(sizeof(SLPAuthBlock) * urlentry->authcount);
|
|
if(urlentry->autharray == 0)
|
|
{
|
|
return SLP_ERROR_INTERNAL_ERROR;
|
|
}
|
|
memset(urlentry->autharray,0,sizeof(SLPAuthBlock) * urlentry->authcount);
|
|
|
|
for(i=0;i<urlentry->authcount;i++)
|
|
{
|
|
result = ParseAuthBlock(buffer,&(urlentry->autharray[i]));
|
|
if(result) return result;
|
|
}
|
|
}
|
|
|
|
urlentry->opaquelen = (char*)buffer->curpos - urlentry->opaque;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int ParseSrvRqst(SLPBuffer buffer, SLPSrvRqst* srvrqst)
|
|
/*--------------------------------------------------------------------------*/
|
|
{
|
|
/* make sure that min size is met */
|
|
if(buffer->end - buffer->curpos < 10)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
|
|
/* parse the prlist */
|
|
srvrqst->prlistlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(srvrqst->prlistlen + 2 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
srvrqst->prlist = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + srvrqst->prlistlen;
|
|
|
|
|
|
/* parse the service type */
|
|
srvrqst->srvtypelen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(srvrqst->srvtypelen + 2 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
srvrqst->srvtype = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + srvrqst->srvtypelen;
|
|
|
|
|
|
/* parse the scope list */
|
|
srvrqst->scopelistlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(srvrqst->scopelistlen + 2 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
srvrqst->scopelist = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + srvrqst->scopelistlen;
|
|
|
|
|
|
/* parse the predicate string */
|
|
srvrqst->predicatever = 2; /* SLPv2 predicate (LDAPv3) */
|
|
srvrqst->predicatelen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(srvrqst->predicatelen + 2 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
srvrqst->predicate = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + srvrqst->predicatelen;
|
|
|
|
|
|
/* parse the slpspi string */
|
|
srvrqst->spistrlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(srvrqst->spistrlen > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
srvrqst->spistr = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + srvrqst->spistrlen;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int ParseSrvRply(SLPBuffer buffer, SLPSrvRply* srvrply)
|
|
/*--------------------------------------------------------------------------*/
|
|
{
|
|
int result;
|
|
int i;
|
|
|
|
/* make sure that min size is met */
|
|
if(buffer->end - buffer->curpos < 4)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
|
|
/* parse out the error code */
|
|
srvrply->errorcode = AsUINT16(buffer->curpos);
|
|
if(srvrply->errorcode)
|
|
{
|
|
/* We better not trust the rest of the packet */
|
|
memset( srvrply, 0, sizeof(SLPSrvRply));
|
|
srvrply->errorcode = AsUINT16(buffer->curpos);
|
|
return 0;
|
|
}
|
|
buffer->curpos = buffer->curpos + 2;
|
|
|
|
/* parse out the url entry count */
|
|
srvrply->urlcount = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
|
|
/* parse out the url entries (if any) */
|
|
if(srvrply->urlcount)
|
|
{
|
|
srvrply->urlarray = (SLPUrlEntry*)xmalloc(sizeof(SLPUrlEntry) * srvrply->urlcount);
|
|
if(srvrply->urlarray == 0)
|
|
{
|
|
return SLP_ERROR_INTERNAL_ERROR;
|
|
}
|
|
memset(srvrply->urlarray,0,sizeof(SLPUrlEntry) * srvrply->urlcount);
|
|
|
|
for(i=0;i<srvrply->urlcount;i++)
|
|
{
|
|
result = ParseUrlEntry(buffer,&(srvrply->urlarray[i]));
|
|
if(result) return result;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
srvrply->urlarray = 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int ParseSrvReg(SLPBuffer buffer, SLPSrvReg* srvreg)
|
|
/*--------------------------------------------------------------------------*/
|
|
{
|
|
int result;
|
|
int i;
|
|
|
|
/* Parse out the url entry */
|
|
result = ParseUrlEntry(buffer,&(srvreg->urlentry));
|
|
if(result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
if(buffer->end - buffer->curpos < 2)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
/* parse the service type */
|
|
srvreg->srvtypelen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(srvreg->srvtypelen + 2 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
srvreg->srvtype = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + srvreg->srvtypelen;
|
|
|
|
|
|
/* parse the scope list */
|
|
srvreg->scopelistlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(srvreg->scopelistlen + 2 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
srvreg->scopelist = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + srvreg->scopelistlen;
|
|
|
|
|
|
/* parse the attribute list*/
|
|
srvreg->attrlistlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(srvreg->attrlistlen + 1 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
srvreg->attrlist = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + srvreg->attrlistlen;
|
|
|
|
|
|
/* parse out attribute auth block count */
|
|
srvreg->authcount = *(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 1;
|
|
|
|
/* parse out the auth block (if any) */
|
|
if(srvreg->authcount)
|
|
{
|
|
srvreg->autharray = (SLPAuthBlock*)xmalloc(sizeof(SLPAuthBlock) * srvreg->authcount);
|
|
if(srvreg->autharray == 0)
|
|
{
|
|
return SLP_ERROR_INTERNAL_ERROR;
|
|
}
|
|
memset(srvreg->autharray,0,sizeof(SLPAuthBlock) * srvreg->authcount);
|
|
|
|
for(i=0;i<srvreg->authcount;i++)
|
|
{
|
|
result = ParseAuthBlock(buffer,&(srvreg->autharray[i]));
|
|
if(result) return result;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int ParseSrvDeReg(SLPBuffer buffer, SLPSrvDeReg* srvdereg)
|
|
/*--------------------------------------------------------------------------*/
|
|
{
|
|
int result;
|
|
|
|
/* make sure that min size is met */
|
|
if(buffer->end - buffer->curpos < 4)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
|
|
|
|
/* parse the scope list */
|
|
srvdereg->scopelistlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(srvdereg->scopelistlen > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
srvdereg->scopelist = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + srvdereg->scopelistlen;
|
|
|
|
/* parse the url entry */
|
|
result = ParseUrlEntry(buffer,&(srvdereg->urlentry));
|
|
if(result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
/* parse the tag list */
|
|
if(buffer->end - buffer->curpos < 2)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
srvdereg->taglistlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(srvdereg->taglistlen > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
srvdereg->taglist = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + srvdereg->taglistlen;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int ParseSrvAck(SLPBuffer buffer, SLPSrvAck* srvack)
|
|
/*--------------------------------------------------------------------------*/
|
|
{
|
|
srvack->errorcode = AsUINT16(buffer->curpos);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int ParseAttrRqst(SLPBuffer buffer, SLPAttrRqst* attrrqst)
|
|
/*--------------------------------------------------------------------------*/
|
|
{
|
|
/* make sure that min size is met */
|
|
if(buffer->end - buffer->curpos < 10)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
|
|
/* parse the prlist */
|
|
attrrqst->prlistlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(attrrqst->prlistlen + 2 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
attrrqst->prlist = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + attrrqst->prlistlen;
|
|
|
|
/* parse the url */
|
|
attrrqst->urllen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(attrrqst->urllen + 2 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
attrrqst->url = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + attrrqst->urllen;
|
|
|
|
|
|
/* parse the scope list */
|
|
attrrqst->scopelistlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(attrrqst->scopelistlen + 2 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
attrrqst->scopelist = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + attrrqst->scopelistlen;
|
|
|
|
|
|
/* parse the taglist string */
|
|
attrrqst->taglistlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(attrrqst->taglistlen + 2 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
attrrqst->taglist = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + attrrqst->taglistlen;
|
|
|
|
|
|
/* parse the slpspi string */
|
|
attrrqst->spistrlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(attrrqst->spistrlen > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
attrrqst->spistr = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + attrrqst->spistrlen;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int ParseAttrRply(SLPBuffer buffer, SLPAttrRply* attrrply)
|
|
/*--------------------------------------------------------------------------*/
|
|
{
|
|
int result;
|
|
int i;
|
|
|
|
/* make sure that min size is met */
|
|
if(buffer->end - buffer->curpos < 4)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
|
|
/* parse out the error code */
|
|
attrrply->errorcode = AsUINT16(buffer->curpos);
|
|
if(attrrply->errorcode)
|
|
{
|
|
/* We better not trust the rest of the packet */
|
|
memset(attrrply,0,sizeof(SLPAttrRply));
|
|
attrrply->errorcode = AsUINT16(buffer->curpos);
|
|
return 0;
|
|
}
|
|
buffer->curpos = buffer->curpos + 2;
|
|
|
|
/* parse out the attrlist */
|
|
attrrply->attrlistlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(attrrply->attrlistlen + 1 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
attrrply->attrlist = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + attrrply->attrlistlen;
|
|
|
|
/* parse out auth block count */
|
|
attrrply->authcount = *(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 1;
|
|
|
|
/* parse out the auth block (if any) */
|
|
if(attrrply->authcount)
|
|
{
|
|
attrrply->autharray = (SLPAuthBlock*)xmalloc(sizeof(SLPAuthBlock) * attrrply->authcount);
|
|
if(attrrply->autharray == 0)
|
|
{
|
|
return SLP_ERROR_INTERNAL_ERROR;
|
|
}
|
|
memset(attrrply->autharray,0,sizeof(SLPAuthBlock) * attrrply->authcount);
|
|
|
|
for(i=0;i<attrrply->authcount;i++)
|
|
{
|
|
result = ParseAuthBlock(buffer,&(attrrply->autharray[i]));
|
|
if(result) return result;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int ParseDAAdvert(SLPBuffer buffer, SLPDAAdvert* daadvert)
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
int result;
|
|
int i;
|
|
|
|
/* make sure that min size is met */
|
|
if(buffer->end - buffer->curpos < 4)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
|
|
/* parse out the error code */
|
|
daadvert->errorcode = AsUINT16(buffer->curpos);
|
|
if(daadvert->errorcode)
|
|
{
|
|
/* We better not trust the rest of the packet */
|
|
memset(daadvert,0,sizeof(SLPDAAdvert));
|
|
daadvert->errorcode = AsUINT16(buffer->curpos);
|
|
return 0;
|
|
}
|
|
buffer->curpos = buffer->curpos + 2;
|
|
|
|
/* parse out the bootstamp */
|
|
if(buffer->end - buffer->curpos < 6)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
daadvert->bootstamp = AsUINT32(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 4;
|
|
|
|
/* parse out the url */
|
|
daadvert->urllen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(daadvert->urllen + 2 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
daadvert->url = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + daadvert->urllen;
|
|
|
|
/* parse the scope list */
|
|
daadvert->scopelistlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(daadvert->scopelistlen + 2 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
daadvert->scopelist = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + daadvert->scopelistlen;
|
|
|
|
/* parse the attr list */
|
|
daadvert->attrlistlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(daadvert->attrlistlen + 2 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
daadvert->attrlist = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + daadvert->attrlistlen;
|
|
|
|
/* parse the SPI list */
|
|
daadvert->spilistlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(daadvert->spilistlen + 1 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
daadvert->spilist = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + daadvert->spilistlen;
|
|
|
|
|
|
/* parse out auth block count */
|
|
daadvert->authcount = *(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 1;
|
|
|
|
/* parse out the auth block (if any) */
|
|
if(daadvert->authcount)
|
|
{
|
|
daadvert->autharray = (SLPAuthBlock*)xmalloc(sizeof(SLPAuthBlock) * daadvert->authcount);
|
|
if(daadvert->autharray == 0)
|
|
{
|
|
return SLP_ERROR_INTERNAL_ERROR;
|
|
}
|
|
memset(daadvert->autharray,0,sizeof(SLPAuthBlock) * daadvert->authcount);
|
|
|
|
for(i=0;i<daadvert->authcount;i++)
|
|
{
|
|
result = ParseAuthBlock(buffer,&(daadvert->autharray[i]));
|
|
if(result) return result;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
int ParseSAAdvert(SLPBuffer buffer, SLPSAAdvert* saadvert)
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
int result;
|
|
int i;
|
|
|
|
/* make sure that min size is met */
|
|
if(buffer->end - buffer->curpos < 4)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
|
|
/* parse out the url */
|
|
saadvert->urllen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(saadvert->urllen + 2 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
saadvert->url = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + saadvert->urllen;
|
|
|
|
/* parse the scope list */
|
|
saadvert->scopelistlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(saadvert->scopelistlen + 2 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
saadvert->scopelist = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + saadvert->scopelistlen;
|
|
|
|
/* parse the attr list */
|
|
saadvert->attrlistlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 2;
|
|
if(saadvert->attrlistlen + 1 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
saadvert->attrlist = buffer->curpos;
|
|
buffer->curpos = buffer->curpos + saadvert->attrlistlen;
|
|
|
|
/* parse out auth block count */
|
|
saadvert->authcount = *(buffer->curpos);
|
|
buffer->curpos = buffer->curpos + 1;
|
|
|
|
/* parse out the auth block (if any) */
|
|
if(saadvert->authcount)
|
|
{
|
|
saadvert->autharray = (SLPAuthBlock*)xmalloc(sizeof(SLPAuthBlock) * saadvert->authcount);
|
|
if(saadvert->autharray == 0)
|
|
{
|
|
return SLP_ERROR_INTERNAL_ERROR;
|
|
}
|
|
memset(saadvert->autharray,0,sizeof(SLPAuthBlock) * saadvert->authcount);
|
|
|
|
for(i=0;i<saadvert->authcount;i++)
|
|
{
|
|
result = ParseAuthBlock(buffer,&(saadvert->autharray[i]));
|
|
if(result) return result;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int ParseSrvTypeRqst(SLPBuffer buffer, SLPSrvTypeRqst* srvtyperqst)
|
|
/*--------------------------------------------------------------------------*/
|
|
{
|
|
/* make sure that min size is met */
|
|
if(buffer->end - buffer->curpos < 6)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
|
|
/* parse the prlist */
|
|
srvtyperqst->prlistlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos += 2;
|
|
if(srvtyperqst->prlistlen + 2 > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
srvtyperqst->prlist = srvtyperqst->prlistlen ? buffer->curpos : 0;
|
|
buffer->curpos += srvtyperqst->prlistlen;
|
|
|
|
/* parse the naming authority if present */
|
|
srvtyperqst->namingauthlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos += 2;
|
|
if(!srvtyperqst->namingauthlen || srvtyperqst->namingauthlen == 0xffff)
|
|
{
|
|
srvtyperqst->namingauth = 0;
|
|
}
|
|
else
|
|
{
|
|
if(srvtyperqst->namingauthlen > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
srvtyperqst->namingauth = buffer->curpos;
|
|
buffer->curpos += srvtyperqst->namingauthlen;
|
|
}
|
|
|
|
/* parse the scope list */
|
|
if(buffer->end - buffer->curpos < 2)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
srvtyperqst->scopelistlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos += 2;
|
|
if(srvtyperqst->scopelistlen > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
srvtyperqst->scopelist = buffer->curpos;
|
|
buffer->curpos += srvtyperqst->scopelistlen;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int ParseSrvTypeRply(SLPBuffer buffer, SLPSrvTypeRply* srvtyperply)
|
|
/*--------------------------------------------------------------------------*/
|
|
{
|
|
/* make sure that min size is met */
|
|
if(buffer->end - buffer->curpos < 4)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
|
|
/* parse out the error code */
|
|
srvtyperply->errorcode = AsUINT16(buffer->curpos);
|
|
if(srvtyperply->errorcode)
|
|
{
|
|
/* We better not trust the rest of the packet */
|
|
memset(srvtyperply,0,sizeof(SLPSrvTypeRply));
|
|
srvtyperply->errorcode = AsUINT16(buffer->curpos);
|
|
return 0;
|
|
}
|
|
buffer->curpos += 2;
|
|
|
|
/* parse out the error srvtype-list length */
|
|
srvtyperply->srvtypelistlen = AsUINT16(buffer->curpos);
|
|
buffer->curpos += 2;
|
|
|
|
if(srvtyperply->srvtypelistlen > buffer->end - buffer->curpos)
|
|
{
|
|
return SLP_ERROR_PARSE_ERROR;
|
|
}
|
|
srvtyperply->srvtypelist = buffer->curpos;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
int ParseExtension(SLPBuffer buffer, SLPMessage message)
|
|
/* Parse extensions *after* all standard protocol fields are parsed */
|
|
/*--------------------------------------------------------------------------*/
|
|
{
|
|
int extid;
|
|
int nextoffset;
|
|
int result = SLP_ERROR_OK;
|
|
|
|
nextoffset = message->header.extoffset;
|
|
while(nextoffset)
|
|
{
|
|
buffer->curpos = buffer->start + nextoffset;
|
|
if(buffer->curpos + 5 >= buffer->end)
|
|
{
|
|
/* Extension takes us past the end of the buffer */
|
|
result = SLP_ERROR_PARSE_ERROR;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
extid = AsUINT16(buffer->curpos);
|
|
buffer->curpos += 2;
|
|
|
|
nextoffset = AsUINT24(buffer->curpos);
|
|
buffer->curpos += 3;
|
|
|
|
switch(extid)
|
|
{
|
|
case SLP_EXTENSION_ID_REG_PID:
|
|
if(message->header.functionid == SLP_FUNCT_SRVREG)
|
|
{
|
|
/* check to see if buffer is large enough to contain the 4 byte pid */
|
|
if(buffer->curpos + 4 > buffer->end)
|
|
{
|
|
result = SLP_ERROR_PARSE_ERROR;
|
|
goto CLEANUP;
|
|
}
|
|
|
|
message->body.srvreg.pid = AsUINT32(buffer->curpos);
|
|
buffer->curpos += 4;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if (extid >= 0x4000 && extid <= 0x7FFF )
|
|
{
|
|
/* This is a required extension. We better error out */
|
|
result = SLP_ERROR_MESSAGE_NOT_SUPPORTED;
|
|
goto CLEANUP;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
CLEANUP:
|
|
|
|
return result;
|
|
}
|
|
|
|
/*=========================================================================*/
|
|
void SLPMessageFreeInternals(SLPMessage message)
|
|
/*=========================================================================*/
|
|
{
|
|
int i;
|
|
|
|
switch(message->header.functionid)
|
|
{
|
|
case SLP_FUNCT_SRVRPLY:
|
|
if(message->body.srvrply.urlarray)
|
|
{
|
|
for(i=0;i<message->body.srvrply.urlcount;i++)
|
|
{
|
|
if(message->body.srvrply.urlarray[i].autharray)
|
|
{
|
|
xfree(message->body.srvrply.urlarray[i].autharray);
|
|
message->body.srvrply.urlarray[i].autharray = 0;
|
|
}
|
|
}
|
|
|
|
xfree(message->body.srvrply.urlarray);
|
|
message->body.srvrply.urlarray = 0;
|
|
}
|
|
break;
|
|
|
|
case SLP_FUNCT_SRVREG:
|
|
if(message->body.srvreg.urlentry.autharray)
|
|
{
|
|
xfree(message->body.srvreg.urlentry.autharray);
|
|
message->body.srvreg.urlentry.autharray = 0;
|
|
}
|
|
if(message->body.srvreg.autharray)
|
|
{
|
|
xfree(message->body.srvreg.autharray);
|
|
message->body.srvreg.autharray = 0;
|
|
}
|
|
break;
|
|
|
|
|
|
case SLP_FUNCT_SRVDEREG:
|
|
if(message->body.srvdereg.urlentry.autharray)
|
|
{
|
|
xfree(message->body.srvdereg.urlentry.autharray);
|
|
message->body.srvdereg.urlentry.autharray = 0;
|
|
}
|
|
break;
|
|
|
|
case SLP_FUNCT_ATTRRPLY:
|
|
if(message->body.attrrply.autharray)
|
|
{
|
|
xfree(message->body.attrrply.autharray);
|
|
message->body.attrrply.autharray = 0;
|
|
}
|
|
break;
|
|
|
|
|
|
case SLP_FUNCT_DAADVERT:
|
|
if(message->body.daadvert.autharray)
|
|
{
|
|
xfree(message->body.daadvert.autharray);
|
|
message->body.daadvert.autharray = 0;
|
|
}
|
|
break;
|
|
|
|
case SLP_FUNCT_SAADVERT:
|
|
if(message->body.saadvert.autharray)
|
|
{
|
|
xfree(message->body.saadvert.autharray);
|
|
message->body.saadvert.autharray = 0;
|
|
}
|
|
break;
|
|
|
|
case SLP_FUNCT_ATTRRQST:
|
|
case SLP_FUNCT_SRVACK:
|
|
case SLP_FUNCT_SRVRQST:
|
|
case SLP_FUNCT_SRVTYPERQST:
|
|
case SLP_FUNCT_SRVTYPERPLY:
|
|
default:
|
|
/* don't do anything */
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*=========================================================================*/
|
|
SLPMessage SLPMessageAlloc()
|
|
/* Allocates memory for a SLP message descriptor */
|
|
/* */
|
|
/* Returns - A newly allocated SLPMessage pointer of NULL on ENOMEM */
|
|
/*=========================================================================*/
|
|
{
|
|
SLPMessage result = (SLPMessage)xmalloc(sizeof(struct _SLPMessage));
|
|
if(result)
|
|
{
|
|
memset(result,0,sizeof(struct _SLPMessage));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/*=========================================================================*/
|
|
SLPMessage SLPMessageRealloc(SLPMessage msg)
|
|
/* Reallocates memory for a SLP message descriptor */
|
|
/* */
|
|
/* Returns - A newly allocated SLPMessage pointer of NULL on ENOMEM */
|
|
/*=========================================================================*/
|
|
{
|
|
if(msg == 0)
|
|
{
|
|
msg = SLPMessageAlloc();
|
|
if(msg == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SLPMessageFreeInternals(msg);
|
|
}
|
|
|
|
return msg;
|
|
}
|
|
|
|
|
|
/*=========================================================================*/
|
|
void SLPMessageFree(SLPMessage message)
|
|
/* Frees memory that might have been allocated by the SLPMessage for */
|
|
/* UrlEntryLists or AuthBlockLists. */
|
|
/* */
|
|
/* message - (IN) the SLPMessage to free */
|
|
/*=========================================================================*/
|
|
{
|
|
if(message)
|
|
{
|
|
SLPMessageFreeInternals(message);
|
|
xfree(message);
|
|
}
|
|
}
|
|
|
|
|
|
/*=========================================================================*/
|
|
int SLPMessageParseBuffer(struct sockaddr_in* peerinfo,
|
|
SLPBuffer buffer,
|
|
SLPMessage message)
|
|
/* Initializes a message descriptor by parsing the specified buffer. */
|
|
/* */
|
|
/* buffer - (IN) pointer the SLPBuffer to parse */
|
|
/* */
|
|
/* message - (OUT) set to describe the message from the buffer */
|
|
/* */
|
|
/* Returns - Zero on success, SLP_ERROR_PARSE_ERROR, or */
|
|
/* SLP_ERROR_INTERNAL_ERROR if out of memory. SLPMessage is */
|
|
/* invalid return is not successful. */
|
|
/* */
|
|
/* WARNING - If successful, pointers in the SLPMessage reference memory in*/
|
|
/* the parsed SLPBuffer. If SLPBufferFree() is called then the */
|
|
/* pointers in SLPMessage will be invalidated. */
|
|
/*=========================================================================*/
|
|
{
|
|
int result;
|
|
|
|
/* Copy in the peer info */
|
|
memcpy(&message->peer,peerinfo,sizeof(message->peer));
|
|
|
|
/* Get ready to parse */
|
|
SLPMessageFreeInternals(message);
|
|
buffer->curpos = buffer->start;
|
|
|
|
/* parse the header first */
|
|
result = SLPMessageParseHeader(buffer,&(message->header));
|
|
if(result == 0)
|
|
{
|
|
/* switch on the function id to parse the body */
|
|
switch(message->header.functionid)
|
|
{
|
|
case SLP_FUNCT_SRVRQST:
|
|
result = ParseSrvRqst(buffer,&(message->body.srvrqst));
|
|
break;
|
|
|
|
case SLP_FUNCT_SRVRPLY:
|
|
result = ParseSrvRply(buffer,&(message->body.srvrply));
|
|
break;
|
|
|
|
case SLP_FUNCT_SRVREG:
|
|
result = ParseSrvReg(buffer,&(message->body.srvreg));
|
|
break;
|
|
|
|
case SLP_FUNCT_SRVDEREG:
|
|
result = ParseSrvDeReg(buffer,&(message->body.srvdereg));
|
|
break;
|
|
|
|
case SLP_FUNCT_SRVACK:
|
|
result = ParseSrvAck(buffer,&(message->body.srvack));
|
|
break;
|
|
|
|
case SLP_FUNCT_ATTRRQST:
|
|
result = ParseAttrRqst(buffer,&(message->body.attrrqst));
|
|
break;
|
|
|
|
case SLP_FUNCT_ATTRRPLY:
|
|
result = ParseAttrRply(buffer,&(message->body.attrrply));
|
|
break;
|
|
|
|
case SLP_FUNCT_DAADVERT:
|
|
result = ParseDAAdvert(buffer,&(message->body.daadvert));
|
|
break;
|
|
|
|
case SLP_FUNCT_SRVTYPERQST:
|
|
result = ParseSrvTypeRqst(buffer,&(message->body.srvtyperqst));
|
|
break;
|
|
|
|
case SLP_FUNCT_SRVTYPERPLY:
|
|
result = ParseSrvTypeRply(buffer,&(message->body.srvtyperply));
|
|
break;
|
|
|
|
case SLP_FUNCT_SAADVERT:
|
|
result = ParseSAAdvert(buffer,&(message->body.saadvert));
|
|
break;
|
|
default:
|
|
result = SLP_ERROR_MESSAGE_NOT_SUPPORTED;
|
|
}
|
|
}
|
|
|
|
if(result == 0 && message->header.extoffset)
|
|
{
|
|
result = ParseExtension(buffer,message);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/*=========================================================================*/
|
|
/* Functions used to parse buffers */
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
unsigned short AsUINT16(const char *charptr)
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
unsigned char *ucp = (unsigned char *) charptr;
|
|
return(ucp[0] << 8) | ucp[1];
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
unsigned int AsUINT24(const char *charptr)
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
unsigned char *ucp = (unsigned char *) charptr;
|
|
return(ucp[0] << 16) | (ucp[1] << 8) | ucp[2];
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
unsigned int AsUINT32(const char *charptr)
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
unsigned char *ucp = (unsigned char *) charptr;
|
|
return(ucp[0] << 24) | (ucp[1] << 16) | (ucp[2] << 8) | ucp[3];
|
|
}
|
|
|
|
/*=========================================================================*/
|
|
/* Functions used to set buffers */
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
void ToUINT16(char *charptr, unsigned int val)
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
charptr[0] = (val >> 8) & 0xff;
|
|
charptr[1] = val & 0xff;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
void ToUINT24(char *charptr, unsigned int val)
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
charptr[0] = (val >> 16) & 0xff;
|
|
charptr[1] = (val >> 8) & 0xff;
|
|
charptr[2] = val & 0xff;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
void ToUINT32(char *charptr, unsigned int val)
|
|
/*-------------------------------------------------------------------------*/
|
|
{
|
|
charptr[0] = (val >> 24) & 0xff;
|
|
charptr[1] = (val >> 16) & 0xff;
|
|
charptr[2] = (val >> 8) & 0xff;
|
|
charptr[3] = val & 0xff;
|
|
}
|