예제 #1
0
/** Read service registrations from a text file.
 *
 * A really big and nasty function that reads service registrations from
 * from a file. Don't look at this too hard or you'll be sick. This is by
 * far the most horrible code in OpenSLP. Please volunteer to rewrite it!
 *
 * "THANK GOODNESS this function is only called at startup" -- Matt
 *
 * @param[in] fd - The file to read from.
 * @param[out] msg - A message describing the SrvReg in buf.
 * @param[out] buf - The buffer used to hold @p message data.
 *
 * @return Zero on success. A value greater than zero on error. A value
 *    less than zero on EOF.
 *
 * @note Eventually the caller needs to call SLPBufferFree and
 *    SLPMessageFree to free memory.
 */
int SLPDRegFileReadSrvReg(FILE * fd, SLPMessage ** msg, SLPBuffer * buf)
{
   char * slider1;
   char * slider2;
   char line[4096];

   struct sockaddr_storage peer;
   int result = 0;
   size_t bufsize = 0;
   size_t langtaglen = 0;
   char * langtag = 0;
   size_t scopelistlen = 0;
   char * scopelist = 0;
   size_t urllen = 0;
   char * url = 0;
   int lifetime = 0;
   size_t srvtypelen = 0;
   char * srvtype = 0;
   size_t attrlistlen = 0;
   char * attrlist = 0;
   SLPBuffer tmp;

#ifdef ENABLE_SLPv2_SECURITY
   unsigned char * urlauth = 0;
   int urlauthlen = 0;
   unsigned char * attrauth = 0;
   int attrauthlen = 0;
#endif

   /* give the out params an initial NULL value */
   *buf = 0;
   *msg = 0;

   /* read the next non-white non-comment line from the stream */
   do
   {
      slider1 = RegFileReadLine(fd, line, 4096);
      if (slider1 == 0)
         return -1;

   } while (*slider1 == 0x0d ||  *slider1 == 0x0a);

   /* Parse the url-props */
   slider2 = strchr(slider1, ',');
   if (slider2)
   {
      /* srvurl */
      *slider2 = 0; /* squash comma to null terminate srvurl */
      url = xstrdup(TrimWhitespace(slider1));
      if (url == 0)
      {
         result = SLP_ERROR_INTERNAL_ERROR;
         goto CLEANUP;
      }
      urllen = strlen(url);

      /* derive srvtype from srvurl */
      srvtype = strstr(slider1, "://");
      if (srvtype == 0)
      {
         result = SLP_ERROR_INVALID_REGISTRATION;
         goto CLEANUP;
      }
      *srvtype = 0;
      srvtype=xstrdup(TrimWhitespace(slider1));
      if (srvtype == 0)
      {
         result = SLP_ERROR_INTERNAL_ERROR;
         goto CLEANUP;
      }
      srvtypelen = strlen(srvtype);
      slider1 = slider2 + 1;

      /*lang*/
      slider2 = strchr(slider1, ',');
      if (slider2)
      {
         *slider2 = 0; /* squash comma to null terminate lang */
         langtag = xstrdup(TrimWhitespace(slider1));
         if (langtag == 0)
         {
            result = SLP_ERROR_INVALID_REGISTRATION;
            goto CLEANUP;
         }
         langtaglen = strlen(langtag);
         slider1 = slider2 + 1;
      }
      else
      {
         result = SLP_ERROR_INVALID_REGISTRATION;
         goto CLEANUP;
      }

      /* ltime */
      slider2 = strchr(slider1,',');
      if (slider2)
      {
         *slider2 = 0; /* squash comma to null terminate ltime */
         lifetime = atoi(slider1);
         slider1 = slider2 + 1;
      }
      else
      {
         lifetime = atoi(slider1);
         slider1 = slider2;
      }
      if (lifetime < 1 || lifetime > SLP_LIFETIME_MAXIMUM)
      {
         result = SLP_ERROR_INVALID_REGISTRATION;
         goto CLEANUP;
      }

      /* get the srvtype if one was not derived by the srvurl */
      if (srvtype == 0)
      {
         srvtype = xstrdup(TrimWhitespace(slider1));
         if (srvtype == 0)
         {
            result = SLP_ERROR_INTERNAL_ERROR;
            goto CLEANUP;
         }
         srvtypelen = strlen(srvtype);
         if (srvtypelen == 0)
         {
            result = SLP_ERROR_INVALID_REGISTRATION;
            goto CLEANUP;
         }
      }
   }
   else
   {
      result = SLP_ERROR_INVALID_REGISTRATION;
      goto CLEANUP;
   }

   /* read all the attributes including the scopelist */
   *line=0;
   while (1)
   {
      slider1 = RegFileReadLine(fd,line,4096);
      if (slider1 == 0)
      {
         result = -1;
         break;
      }
      if (*slider1 == 0x0d || *slider1 == 0x0a)
         break;

      /* Check to see if it is the scopes line */
      /* FIXME We can collapse the scope stuff into the value getting and
         just make it a special case (do strcmp on the tag as opposed to the
         line) of attribute getting. */
      if (strncasecmp(slider1,"scopes", 6) == 0)
      {
         /* found scopes line */
         slider2 = strchr(slider1,'=');
         if (slider2)
         {
            slider2++;
            if (*slider2)
            {
               /* just in case some idiot puts multiple scopes lines */
               if (scopelist)
               {
                  result = SLP_ERROR_SCOPE_NOT_SUPPORTED;
                  goto CLEANUP;
               }

               /* make sure there are no spaces in the scope list
      NOTE: There's nothing in the spec that indicates that
      scopes can't contain spaces. Commenting out for now. --jmc
               if (strchr(slider2, ' '))
               {
                  result = SLP_ERROR_SCOPE_NOT_SUPPORTED;
                  goto CLEANUP;
               } */

               scopelist = xstrdup(TrimWhitespace(slider2));
               if (scopelist == 0)
               {
                  result = SLP_ERROR_INTERNAL_ERROR;
                  goto CLEANUP;
               }
               scopelistlen = strlen(scopelist);
            }
         }
      }
      else
      {
         /* line contains an attribute (slow but it works)*/
         /* TODO Fix this so we do not have to realloc memory each time! */
         TrimWhitespace(slider1);

         if (attrlist == 0)
         {
            attrlistlen += strlen(slider1) + 2;
            attrlist = xmalloc(attrlistlen + 1);
            if (attrlist == 0)
            {
               result = SLP_ERROR_INTERNAL_ERROR;
               goto CLEANUP;
            }
            *attrlist = 0;
         }
         else
         {
            char * tmp_attrlist;
            attrlistlen += strlen(slider1) + 3;
            if ((tmp_attrlist = xrealloc(attrlist, attrlistlen + 1)) == 0)
            {
               xfree(attrlist);
               result = SLP_ERROR_INTERNAL_ERROR;
               goto CLEANUP;
            }
            attrlist = tmp_attrlist;
            strcat(attrlist, ",");
         }

         if (attrlist == 0)
         {
            result = SLP_ERROR_INTERNAL_ERROR;
            goto CLEANUP;
         }

         /* we need special case for keywords (why do we need these)
            they seem like a waste of code.  Why not just use booleans */
         if (strchr(slider1, '='))
         {
            /* normal attribute (with '=') */
            strcat(attrlist, "(");
            strcat(attrlist, slider1);
            strcat(attrlist, ")");
         }
         else
         {
            /* keyword (no '=') */
            attrlistlen -= 2; /* subtract 2 bytes for no '(' or ')' */
            strcat(attrlist, slider1);
         }
      }
   }

   /* Set the scope set in properties if not is set */
   if (scopelist == 0)
   {
      scopelist = xstrdup(G_SlpdProperty.useScopes);
      if (scopelist == 0)
      {
         result = SLP_ERROR_INTERNAL_ERROR;
         goto CLEANUP;
      }
      scopelistlen = G_SlpdProperty.useScopesLen;
   }

#ifdef ENABLE_SLPv2_SECURITY
   /* generate authentication blocks */
   if (G_SlpdProperty.securityEnabled)
   {
      SLPAuthSignUrl(G_SlpdSpiHandle, 0, 0, urllen, url,
            &urlauthlen, &urlauth);
      SLPAuthSignString(G_SlpdSpiHandle, 0, 0, attrlistlen, attrlist,
            &attrauthlen, &attrauth);
   }
#endif

   /* allocate buffer for the SrvReg Message */
   bufsize = 14 + langtaglen;    /* 14 bytes for header    */
   bufsize += urllen + 6;        /*  1 byte for reserved   */
                                 /*  2 bytes for lifetime  */
                                 /*  2 bytes for urllen    */
                                 /*  1 byte for authcount  */
   bufsize += srvtypelen + 2;    /*  2 bytes for len field */
   bufsize += scopelistlen + 2;  /*  2 bytes for len field */
   bufsize += attrlistlen + 2;   /*  2 bytes for len field */
   bufsize += 1;                 /*  1 byte for authcount  */

#ifdef ENABLE_SLPv2_SECURITY
   bufsize += urlauthlen;
   bufsize += attrauthlen;
#endif

   tmp = *buf = SLPBufferAlloc(bufsize);
   if (tmp == 0)
   {
      result = SLP_ERROR_INTERNAL_ERROR;
      goto CLEANUP;
   }

   /* now build the SrvReg Message */

   /* version */
   *tmp->curpos++ = 2;

   /* function id */
   *tmp->curpos++ = SLP_FUNCT_SRVREG;

   /* length */
   PutUINT24(&tmp->curpos, bufsize);

   /* flags */
   PutUINT16(&tmp->curpos, 0);

   /* ext offset */
   PutUINT24(&tmp->curpos, 0);

   /* xid */
   PutUINT16(&tmp->curpos, 0);

   /* lang tag len */
   PutUINT16(&tmp->curpos, langtaglen);

   /* lang tag */
   memcpy(tmp->curpos, langtag, langtaglen);
   tmp->curpos += langtaglen;

   /* url-entry reserved */
   *tmp->curpos++ = 0;

   /* url-entry lifetime */
   PutUINT16(&tmp->curpos, lifetime);

   /* url-entry urllen */
   PutUINT16(&tmp->curpos, urllen);

   /* url-entry url */
   memcpy(tmp->curpos, url, urllen);
   tmp->curpos += urllen;

   /* url-entry authblock */
#ifdef ENABLE_SLPv2_SECURITY
   if (urlauth)
   {
      /* authcount */
      *tmp->curpos++ = 1;

      /* authblock */
      memcpy(tmp->curpos, urlauth, urlauthlen);
      tmp->curpos += urlauthlen;
   }
   else
#endif
      *tmp->curpos++ = 0;

   /* service type */
   PutUINT16(&tmp->curpos, srvtypelen);
   memcpy(tmp->curpos, srvtype, srvtypelen);
   tmp->curpos += srvtypelen;

   /* scope list */
   PutUINT16(&tmp->curpos, scopelistlen);
   memcpy(tmp->curpos, scopelist, scopelistlen);
   tmp->curpos += scopelistlen;

   /* attr list */
   PutUINT16(&tmp->curpos, attrlistlen);
   memcpy(tmp->curpos, attrlist, attrlistlen);
   tmp->curpos += attrlistlen;

   /* attribute auth block */
#ifdef ENABLE_SLPv2_SECURITY
   if (attrauth)
   {
      /* authcount */
      *tmp->curpos++ = 1;

      /* authblock */
      memcpy(tmp->curpos, attrauth, attrauthlen);
      tmp->curpos += attrauthlen;
   }
   else
#endif
      *tmp->curpos++ = 0;

   /* okay, now comes the really stupid (and lazy part) */
   *msg = SLPMessageAlloc();
   if (*msg == 0)
   {
      SLPBufferFree(*buf);
      *buf = 0;
      result = SLP_ERROR_INTERNAL_ERROR;
      goto CLEANUP;
   }

   /* this should be ok even if we are not supporting IPv4,
    * since it's a static service
    */
   memset(&peer, 0, sizeof(struct sockaddr_in));
   peer.ss_family = AF_UNSPEC;
   ((struct sockaddr_in *)&peer)->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
   result = SLPMessageParseBuffer(&peer, &peer, *buf, *msg);
   (*msg)->body.srvreg.source = SLP_REG_SOURCE_STATIC;

CLEANUP:

   /* check for errors and free memory */
   switch(result)
   {
      case SLP_ERROR_INTERNAL_ERROR:
         SLPDLog("\nERROR: Out of memory one reg file line:\n   %s\n", line);
         break;

      case SLP_ERROR_INVALID_REGISTRATION:
         SLPDLog("\nERROR: Invalid reg file format near:\n   %s\n", line);
         break;

      case SLP_ERROR_SCOPE_NOT_SUPPORTED:
         SLPDLog("\nERROR: Duplicate scopes or scope list with "
               "embedded spaces near:\n   %s\n", line);
         break;

      default:
         break;
   }

   xfree(langtag);
   xfree(scopelist);
   xfree(url);
   xfree(srvtype);
   xfree(attrlist);

#ifdef ENABLE_SLPv2_SECURITY
   xfree(urlauth);
   xfree(attrauth);
#endif

   return result;
}
예제 #2
0
/** Formats and sends an SLPReg wire buffer request.
 *
 * @param handle - The OpenSLP session handle, containing request 
 *    parameters. See docs for SLPReg.
 *
 * @return Zero on success, or an SLP API error code.
 * 
 * @internal
 */
static SLPError ProcessSrvReg(SLPHandleInfo * handle)
{
   sockfd_t sock;
   uint8_t * buf;
   uint8_t * curpos;
   SLPError serr;
   size_t extoffset = 0;
   int urlauthlen = 0;
   uint8_t * urlauth = 0;
   int attrauthlen = 0;
   uint8_t * attrauth = 0;
   SLPBoolean watchRegPID;
   struct sockaddr_storage saaddr;

#ifdef ENABLE_SLPv2_SECURITY
   if (SLPPropertyAsBoolean("net.slp.securityEnabled"))
   {
      int err = SLPAuthSignUrl(handle->hspi, 0, 0, handle->params.reg.urllen,
            handle->params.reg.url, &urlauthlen, &urlauth);
      if (err == 0)
         err = SLPAuthSignString(handle->hspi, 0, 0,
               handle->params.reg.attrlistlen, handle->params.reg.attrlist,
               &attrauthlen, &attrauth);
      if (err != 0)
         return SLP_AUTHENTICATION_ABSENT;
   }
#endif

   /* Should we send the "Watch Registration PID" extension? */
   watchRegPID = SLPPropertyAsBoolean("net.slp.watchRegistrationPID");

/*  0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                          <URL-Entry>                          \
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | length of service type string |        <service-type>         \
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     length of <scope-list>    |         <scope-list>          \
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  length of attr-list string   |          <attr-list>          \
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |# of AttrAuths |(if present) Attribute Authentication Blocks...\
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
   |    WATCH-PID extension ID     |    next extension offset      \
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
   |  nxo (cont)   |     process identifier to be monitored        \
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
   |  PID (cont)   |
   +-+-+-+-+-+-+-+-+ */

   buf = curpos = xmalloc(
         + SizeofURLEntry(handle->params.reg.urllen, urlauthlen)
         + 2 + handle->params.reg.srvtypelen
         + 2 + handle->params.reg.scopelistlen
         + 2 + handle->params.reg.attrlistlen
         + 1 + attrauthlen 
         + (watchRegPID? (2 + 3 + 4): 0));
   if (buf == 0)
   {
      xfree(urlauth);
      xfree(attrauth);
      return SLP_MEMORY_ALLOC_FAILED;
   }

   /* URL entry */
   PutURLEntry(&curpos, handle->params.reg.lifetime, handle->params.reg.url, 
         handle->params.reg.urllen, urlauth, urlauthlen);

   /* <service-type> */
   PutL16String(&curpos, handle->params.reg.srvtype, 
         handle->params.reg.srvtypelen);

   /* <scope-list> */
   PutL16String(&curpos, handle->params.reg.scopelist,
         handle->params.reg.scopelistlen);

   /* <attr-list> */
   PutL16String(&curpos, handle->params.reg.attrlist, 
         handle->params.reg.attrlistlen);

   /** @todo Handle multiple attribute authentication blocks. */

   /* Attribute Authentication Blocks */
   *curpos++ = attrauth? 1: 0;
   memcpy(curpos, attrauth, attrauthlen);
   curpos += attrauthlen;

   /* SLP_EXTENSION_ID_REG_PID */
   if (watchRegPID)
   {
      extoffset = curpos - buf;

      /** @todo In some future code base, this should be changed to use the 
       * non-deprecated official version, SLP_EXTENSION_ID_REG_PID. For now
       * we need to use the EXPerimental version in order to interoperate
       * properly with OpenSLP 1.x SA's.
       */

      PutUINT16(&curpos, SLP_EXTENSION_ID_REG_PID_EXP);
      PutUINT24(&curpos, 0);
      PutUINT32(&curpos, SLPPidGet());
   }

   /* Call the Request-Reply engine. */
   sock = NetworkConnectToSA(handle, handle->params.reg.scopelist,
         handle->params.reg.scopelistlen, &saaddr);
   if (sock != SLP_INVALID_SOCKET)
   {
      serr = NetworkRqstRply(sock, &saaddr, handle->langtag, extoffset,
            buf, SLP_FUNCT_SRVREG, curpos - buf, CallbackSrvReg, handle);
      if (serr)
         NetworkDisconnectSA(handle);
   }
   else
      serr = SLP_NETWORK_INIT_FAILED;    

   xfree(buf);
   xfree(urlauth);
   xfree(attrauth);

   return serr;
}
예제 #3
0
/** 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;
}        
예제 #4
0
/** Process a general service deregistration 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 A non-zero value if @p message should be silently dropped.
 *
 * @internal
 */
static int ProcessSrvDeReg(SLPMessage * message, 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  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
      /* malidate 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 
         || SLPNetIsMCast(&message->peer))
   {
      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->curpos++ = 2;

   /* function id */
   *result->curpos++ = SLP_FUNCT_SRVACK;

   /* length */
   PutUINT24(&result->curpos, message->header.langtaglen + 16);

   /* flags */
   PutUINT16(&result->curpos, 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 the errorcode */
   PutUINT16(&result->curpos, errorcode);

FINISHED:

   *sendbuf = result;
   return errorcode;
}
예제 #5
0
/** Process an SA SrvRequest 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 ProcessSASrvRqst(SLPMessage * message, SLPBuffer * sendbuf,
      int errorcode)
{
   char localaddr_str[INET6_ADDRSTRLEN + 2];
   size_t 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.urlPrefixLen;
      localaddr_str[0] = 0;
      if (message->localaddr.ss_family == AF_INET) 
         inet_ntop(message->localaddr.ss_family, &((struct sockaddr_in *)
               &message->localaddr)->sin_addr, localaddr_str, 
               sizeof(localaddr_str));
      else if (message->localaddr.ss_family == AF_INET6) 
      {
         strcpy(localaddr_str, "[");
         inet_ntop(message->localaddr.ss_family, &((struct sockaddr_in6 *) 
               &message->localaddr)->sin6_addr, &localaddr_str[1], 
               sizeof(localaddr_str) - 1);
         strcat(localaddr_str, "]");
      }
      size += strlen(localaddr_str);
      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->curpos++ = 2;

      /* function id */
      *result->curpos++ = SLP_FUNCT_SAADVERT;

      /* 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 SAAdvert */

      /* url len */
      PutUINT16(&result->curpos, G_SlpdProperty.urlPrefixLen 
            + strlen(localaddr_str));

      /* url */
      memcpy(result->curpos, G_SlpdProperty.urlPrefix,
            G_SlpdProperty.urlPrefixLen);
      result->curpos += G_SlpdProperty.urlPrefixLen;
      memcpy(result->curpos, localaddr_str, strlen(localaddr_str));
      result->curpos += strlen(localaddr_str);

      /* scope list len */
      PutUINT16(&result->curpos, G_SlpdProperty.useScopesLen);

      /* scope list */
      memcpy(result->curpos, G_SlpdProperty.useScopes,
            G_SlpdProperty.useScopesLen);
      result->curpos += G_SlpdProperty.useScopesLen;

      /* attr list len */
      /* PutUINT16(&result->curpos, G_SlpdProperty.SAAttributesLen) */
      PutUINT16(&result->curpos, 0);

      /* attr list */
      /* memcpy(result->curpos, G_SlpdProperty.SAAttributes,
            G_SlpdProperty.SAAttributesLen) */

      /* authblock count */
      *result->curpos++ = 0;
   }
   else
      errorcode = SLP_ERROR_SCOPE_NOT_SUPPORTED;

FINISHED:

   *sendbuf = result;

   return errorcode;
}
예제 #6
0
/** Process a general service 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 ProcessSrvRqst(SLPMessage * message, SLPBuffer * sendbuf, 
      int errorcode)
{
   int i;
   SLPUrlEntry * urlentry;
   SLPDDatabaseSrvRqstResult * db = 0;
   size_t 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 are
      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)
      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 
            || SLPNetIsMCast(&(message->peer)))
      {
         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->curpos++ = 2;

   /* function id */
   *result->curpos++ = SLP_FUNCT_SRVRPLY;

   /* 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 SrvRply */

   /* error code*/
   PutUINT16(&result->curpos, errorcode);
   if (errorcode == 0)
   {
      /* urlentry count */
      PutUINT16(&result->curpos, db->urlcount);
      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;        

            /* url-entry lifetime */
            PutUINT16(&result->curpos, urlentry->lifetime);

            /* url-entry urllen */
            PutUINT16(&result->curpos, urlentry->urllen);

            /* url-entry url */
            memcpy(result->curpos, urlentry->url, urlentry->urllen);
            result->curpos += urlentry->urllen;

            /* url-entry auths */
            *result->curpos++ = 0;
         }
         else
#endif
         {
            /* Use an opaque copy if available (and authentication is 
             * not being used).
             */

            /* TRICKY: Fix up the lifetime. */
            TO_UINT16(urlentry->opaque + 1, urlentry->lifetime);
            memcpy(result->curpos, urlentry->opaque, urlentry->opaquelen);
            result->curpos += urlentry->opaquelen;
         }
      }
   }
   else
      PutUINT16(&result->curpos, 0); /* set urlentry count to 0*/

FINISHED:   

   if (db) 
      SLPDDatabaseSrvRqstEnd(db);

   *sendbuf = result;

   return errorcode;
}
예제 #7
0
/** Process a SrvTypeRequest 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 ProcessSrvTypeRqst(SLPMessage * message, SLPBuffer * sendbuf,
      int errorcode)
{
   size_t 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)
      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 
            || SLPNetIsMCast(&(message->peer)))
      {
         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 len */
   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->curpos++ = 2;

   /* function id */
   *result->curpos++ = SLP_FUNCT_SRVTYPERPLY;

   /* 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 SrvTypeRply */

   /* error code*/
   PutUINT16(&result->curpos, errorcode);
   if (errorcode == 0)
   {
      /* length of srvtype-list */
      PutUINT16(&result->curpos, db->srvtypelistlen);
      memcpy(result->curpos, db->srvtypelist, db->srvtypelistlen);
      result->curpos += db->srvtypelistlen;
   }

FINISHED:   

   if (db) 
      SLPDDatabaseSrvTypeRqstEnd(db);

   *sendbuf = result;

   return errorcode;
}