/*=========================================================================*/ SLPDDatabaseEntry* SLPDRegFileReadEntry(FILE* fd, SLPDDatabaseEntry** entry) /* A really big and nasty function that reads an entry SLPDDatabase entry */ /* from a file. Don't look at this too hard or you'll be sick */ /* */ /* fd (IN) file to read from */ /* */ /* entry (OUT) Address of a pointer that will be set to the location of */ /* a dynamically allocated SLPDDatabase entry. The entry */ /* must be freed */ /* */ /* Returns *entry or null on error. */ /*=========================================================================*/ { char* slider1; char* slider2; char line[4096]; /* give the out param a value */ *entry = 0; /*----------------------------------------------------------*/ /* read the next non-white non-comment line from the stream */ /*----------------------------------------------------------*/ do { slider1 = RegFileReadLine(fd,line,4096); if(slider1 == 0) { /* read through the whole file and found no entries */ return 0; } }while(*slider1 == 0x0d || *slider1 == 0x0a); /*---------------------------*/ /* Allocate a database entry */ /*---------------------------*/ *entry = (SLPDDatabaseEntry*)malloc(sizeof(SLPDDatabaseEntry)); if(entry == 0) { SLPFatal("Out of memory!\n"); return 0; } memset(*entry,0,sizeof(SLPDDatabaseEntry)); /*---------------------*/ /* Parse the url-props */ /*---------------------*/ slider2 = strchr(slider1,','); if(slider2) { /* srvurl */ *slider2 = 0; /* squash comma to null terminate srvurl */ (*entry)->url = strdup(TrimWhitespace(slider1)); if((*entry)->url == 0) { SLPLog("Out of memory reading srvurl from regfile line ->%s",line); goto SLPDREGFILEREADENTRY_ERROR1; } (*entry)->urllen = strlen((*entry)->url); /* derive srvtype from srvurl if srvurl is "service:" scheme URL */ if(strncasecmp(slider1,"service:",8)==0) { (*entry)->srvtype = strstr(slider1,"://"); if((*entry)->srvtype == 0) { SLPLog("Looks like a bad url on regfile line ->%s",line); goto SLPDREGFILEREADENTRY_ERROR1; } *(*entry)->srvtype = 0; (*entry)->srvtype=strdup(TrimWhitespace(slider1)); (*entry)->srvtypelen = strlen((*entry)->srvtype); } slider1 = slider2 + 1; /*lang*/ slider2 = strchr(slider1,','); if(slider2) { *slider2 = 0; /* squash comma to null terminate lang */ (*entry)->langtag = strdup(TrimWhitespace(slider1)); if((*entry)->langtag == 0) { SLPLog("Out of memory reading langtag from regfile line ->%s",line); goto SLPDREGFILEREADENTRY_ERROR1; } (*entry)->langtaglen = strlen((*entry)->langtag); slider1 = slider2 + 1; } else { SLPLog("Expected language tag near regfile line ->%s\n",line); goto SLPDREGFILEREADENTRY_ERROR1; } /* ltime */ slider2 = strchr(slider1,','); if(slider2) { *slider2 = 0; /* squash comma to null terminate ltime */ (*entry)->lifetime = atoi(slider1); slider1 = slider2 + 1; } else { (*entry)->lifetime = atoi(slider1); slider1 = slider2; } if((*entry)->lifetime < 1 || (*entry)->lifetime > 0xffff) { SLPLog("Invalid lifetime near regfile line ->%s\n",line); goto SLPDREGFILEREADENTRY_ERROR1; } /* get the srvtype if one was not derived by the srvurl*/ if((*entry)->srvtype == 0) { (*entry)->srvtype = strdup(TrimWhitespace(slider1)); if((*entry)->srvtype == 0) { SLPLog("Out of memory reading srvtype from regfile line ->%s",line); goto SLPDREGFILEREADENTRY_ERROR1; } (*entry)->srvtypelen = strlen((*entry)->srvtype); if((*entry)->srvtypelen == 0) { SLPLog("Expected to derive service-type near regfile line -> %s\n",line); goto SLPDREGFILEREADENTRY_ERROR1; } } } else { SLPLog("Expected to find srv-url near regfile line -> %s\n",line); goto SLPDREGFILEREADENTRY_ERROR1; } /*-------------------------------------------------*/ /* Read all the attributes including the scopelist */ /*-------------------------------------------------*/ *line=0; while(1) { if(RegFileReadLine(fd,line,4096) == 0) { break; } if(*line == 0x0d || *line == 0x0a) { break; } /* Check to see if it is the scopes line */ if(strncasecmp(line,"scopes",6) == 0) { /* found scopes line */ slider1 = line; slider2 = strchr(slider1,'='); if(slider2) { slider2++; if(*slider2) { /* just in case some idiot puts multiple scopes lines */ if((*entry)->scopelist) { SLPLog("scopes already defined previous to regfile line ->%s",line); goto SLPDREGFILEREADENTRY_ERROR1; } (*entry)->scopelist=strdup(TrimWhitespace(slider2)); if((*entry)->scopelist == 0) { SLPLog("Out of memory adding scopes from regfile line ->%s",line); goto SLPDREGFILEREADENTRY_ERROR1; } (*entry)->scopelistlen = strlen((*entry)->scopelist); } } } else { /* line contains an attribute (slow but it works)*/ /* TODO Fix this so we do not have to realloc memory each time! */ TrimWhitespace(line); (*entry)->attrlistlen += strlen(line) + 2; if((*entry)->attrlist == 0) { (*entry)->attrlist = malloc((*entry)->attrlistlen + 1); *(*entry)->attrlist = 0; } else { (*entry)->attrlist = realloc((*entry)->attrlist, (*entry)->attrlistlen + 1); } if((*entry)->attrlist == 0) { SLPLog("Out of memory adding DEFAULT scope\n"); goto SLPDREGFILEREADENTRY_ERROR1; } strcat((*entry)->attrlist,"("); strcat((*entry)->attrlist,line); strcat((*entry)->attrlist,")"); } } /* Set the scope to default if not is set */ if((*entry)->scopelist == 0) { (*entry)->scopelist=strdup("DEFAULT"); if((*entry)->scopelist == 0) { SLPLog("Out of memory adding DEFAULT scope\n"); goto SLPDREGFILEREADENTRY_ERROR1; } (*entry)->scopelistlen = 7; } return *entry; SLPDREGFILEREADENTRY_ERROR1: if(*entry) { if((*entry)->srvtype) free((*entry)->srvtype); if((*entry)->url) free((*entry)->url); if((*entry)->langtag) free((*entry)->langtag); if((*entry)->scopelist) free((*entry)->scopelist); if((*entry)->attrlist) free((*entry)->attrlist); free(*entry); *entry = 0; } return 0; }
/*=========================================================================*/ SLPDDatabaseEntry* SLPDRegFileReadEntry(FILE* fd, SLPDDatabaseEntry** entry) /* A really big and nasty function that reads an entry SLPDDatabase entry */ /* from a file. Don't look at this too hard or you'll be sick */ /* */ /* fd (IN) file to read from */ /* */ /* entry (OUT) Address of a pointer that will be set to the location of */ /* a dynamically allocated SLPDDatabase entry. The entry */ /* must be freed */ /* */ /* Returns *entry or null on error. */ /*=========================================================================*/ { char* slider1; char* slider2; char line[4096]; /* give the out param a value */ *entry = 0; /*----------------------------------------------------------*/ /* read the next non-white non-comment line from the stream */ /*----------------------------------------------------------*/ do { slider1 = RegFileReadLine(fd,line,4096); if(slider1 == 0) { /* read through the whole file and found no entries */ return 0; } }while(*slider1 == 0x0d || *slider1 == 0x0a); /*---------------------------*/ /* Allocate a database entry */ /*---------------------------*/ *entry = SLPDDatabaseEntryAlloc(); if(entry == 0) { SLPFatal("Out of memory!\n"); return 0; } /* entries read from the .reg file are always local */ (*entry)->islocal = 1; /*---------------------*/ /* Parse the url-props */ /*---------------------*/ slider2 = strchr(slider1,','); if(slider2) { /* srvurl */ *slider2 = 0; /* squash comma to null terminate srvurl */ (*entry)->url = strdup(TrimWhitespace(slider1)); if((*entry)->url == 0) { SLPLog("Out of memory reading srvurl from regfile line ->%s",line); goto SLPD_ERROR; } (*entry)->urllen = strlen((*entry)->url); /* derive srvtype from srvurl */ (*entry)->srvtype = strstr(slider1,"://"); if((*entry)->srvtype == 0) { SLPLog("Looks like a bad url on regfile line ->%s",line); goto SLPD_ERROR; } *(*entry)->srvtype = 0; (*entry)->srvtype=strdup(TrimWhitespace(slider1)); (*entry)->srvtypelen = strlen((*entry)->srvtype); slider1 = slider2 + 1; /*lang*/ slider2 = strchr(slider1,','); if(slider2) { *slider2 = 0; /* squash comma to null terminate lang */ (*entry)->langtag = strdup(TrimWhitespace(slider1)); if((*entry)->langtag == 0) { SLPLog("Out of memory reading langtag from regfile line ->%s",line); goto SLPD_ERROR; }(*entry)->langtaglen = strlen((*entry)->langtag); slider1 = slider2 + 1; } else { SLPLog("Expected language tag near regfile line ->%s\n",line); goto SLPD_ERROR; } /* ltime */ slider2 = strchr(slider1,','); if(slider2) { *slider2 = 0; /* squash comma to null terminate ltime */ (*entry)->lifetime = atoi(slider1); slider1 = slider2 + 1; } else { (*entry)->lifetime = atoi(slider1); slider1 = slider2; } if((*entry)->lifetime < 1 || (*entry)->lifetime > 0xffff) { SLPLog("Invalid lifetime near regfile line ->%s\n",line); goto SLPD_ERROR; } /* get the srvtype if one was not derived by the srvurl*/ if((*entry)->srvtype == 0) { (*entry)->srvtype = strdup(TrimWhitespace(slider1)); if((*entry)->srvtype == 0) { SLPLog("Out of memory reading srvtype from regfile line ->%s",line); goto SLPD_ERROR; } (*entry)->srvtypelen = strlen((*entry)->srvtype); if((*entry)->srvtypelen == 0) { SLPLog("Expected to derive service-type near regfile line -> %s\n",line); goto SLPD_ERROR; } } } else { SLPLog("Expected to find srv-url near regfile line -> %s\n",line); goto SLPD_ERROR; } /*-------------------------------------------------*/ /* Read all the attributes including the scopelist */ /*-------------------------------------------------*/ *line=0; while(1) { if(RegFileReadLine(fd,line,4096) == 0) { break; } if(*line == 0x0d || *line == 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(line,"scopes",6) == 0) { /* found scopes line */ slider1 = line; slider2 = strchr(slider1,'='); if(slider2) { slider2++; if(*slider2) { /* just in case some idiot puts multiple scopes lines */ if((*entry)->scopelist) { SLPLog("scopes already defined previous to regfile line ->%s",line); goto SLPD_ERROR; } (*entry)->scopelist=strdup(TrimWhitespace(slider2)); if((*entry)->scopelist == 0) { SLPLog("Out of memory adding scopes from regfile line ->%s",line); goto SLPD_ERROR; } (*entry)->scopelistlen = strlen((*entry)->scopelist); } } } else { #ifdef USE_PREDICATES char *tag; /* Will point to the start of the tag. */ char *val; /* Will point to the start of the value. */ char *end; char *tag_end; tag = line; /*** Elide ws. ***/ while(isspace(*tag)) { tag++; } tag_end = tag; /*** Find tag end. ***/ while(*tag_end && (!isspace(*tag_end)) && (*tag_end != '=')) { tag_end++; } while(*tag_end && *tag_end != '=') { tag_end++; } *tag_end = 0; /*** Find value start. ***/ val = tag_end + 1; /*** Elide ws. ***/ while(isspace(*val)) { val++; } /*** Elide trailing ws. ***/ end = val; /** Find tag end. **/ while(*end != 0) { end++; } /*** Back up over trailing whitespace. ***/ end--; while(isspace(*end)) { *end = 0; /* Overwrite ws. */ end--; } SLPAttrSet_guess((*entry)->attr, tag, val, SLP_ADD); #else /* line contains an attribute (slow but it works)*/ /* TODO Fix this so we do not have to realloc memory each time! */ TrimWhitespace(line); (*entry)->attrlistlen += strlen(line) + 2; if((*entry)->attrlist == 0) { (*entry)->attrlist = malloc((*entry)->attrlistlen + 1); *(*entry)->attrlist = 0; } else { (*entry)->attrlist = realloc((*entry)->attrlist, (*entry)->attrlistlen + 2); strcat((*entry)->attrlist,","); } if((*entry)->attrlist == 0) { SLPLog("Out of memory adding DEFAULT scope\n"); goto SLPD_ERROR; } strcat((*entry)->attrlist,"("); strcat((*entry)->attrlist,line); strcat((*entry)->attrlist,")"); #endif } } /* Set the scope set in properties if not is set */ if((*entry)->scopelist == 0) { (*entry)->scopelist=strdup(G_SlpdProperty.useScopes); if((*entry)->scopelist == 0) { SLPLog("Out of memory adding DEFAULT scope\n"); goto SLPD_ERROR; } (*entry)->scopelistlen = G_SlpdProperty.useScopesLen; } return *entry; SLPD_ERROR: if(*entry) { SLPDDatabaseEntryFree(*entry); *entry = 0; } return 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; }