1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright (c) 1999 by Sun Microsystems, Inc. 24*7c478bd9Sstevel@tonic-gate * All rights reserved. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <stdio.h> 30*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 31*7c478bd9Sstevel@tonic-gate #include <ctype.h> 32*7c478bd9Sstevel@tonic-gate #include <string.h> 33*7c478bd9Sstevel@tonic-gate #include <syslog.h> 34*7c478bd9Sstevel@tonic-gate #include <slp-internal.h> 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate /* 37*7c478bd9Sstevel@tonic-gate * URL parsing 38*7c478bd9Sstevel@tonic-gate */ 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate #define SLP_IANA "iana" 41*7c478bd9Sstevel@tonic-gate #define SERVICE_PREFIX "service" 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate /* service type struct */ 44*7c478bd9Sstevel@tonic-gate typedef struct slp_type { 45*7c478bd9Sstevel@tonic-gate SLPBoolean isServiceURL; 46*7c478bd9Sstevel@tonic-gate char *atype; 47*7c478bd9Sstevel@tonic-gate char *ctype; 48*7c478bd9Sstevel@tonic-gate char *na; 49*7c478bd9Sstevel@tonic-gate char *orig; 50*7c478bd9Sstevel@tonic-gate } slp_type_t; 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate static SLPError parseType(char *, slp_type_t *); 53*7c478bd9Sstevel@tonic-gate static int validateTypeChars(char *); 54*7c478bd9Sstevel@tonic-gate static int validateTransport(char *); 55*7c478bd9Sstevel@tonic-gate static int checkURLString(char *); 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate SLPError SLPParseSrvURL(char *pcSrvURL, SLPSrvURL** ppSrvURL) { 58*7c478bd9Sstevel@tonic-gate char *p, *q, *r; 59*7c478bd9Sstevel@tonic-gate SLPSrvURL *surl; 60*7c478bd9Sstevel@tonic-gate slp_type_t type[1]; 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate if (!pcSrvURL || !ppSrvURL) { 63*7c478bd9Sstevel@tonic-gate return (SLP_PARAMETER_BAD); 64*7c478bd9Sstevel@tonic-gate } 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate *ppSrvURL = NULL; 67*7c478bd9Sstevel@tonic-gate if (!checkURLString((char *)pcSrvURL)) 68*7c478bd9Sstevel@tonic-gate return (SLP_PARSE_ERROR); 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate if (!(surl = malloc(sizeof (*surl)))) { 71*7c478bd9Sstevel@tonic-gate slp_err(LOG_CRIT, 0, "SLPParseSrvURL", "out of memory"); 72*7c478bd9Sstevel@tonic-gate return (SLP_MEMORY_ALLOC_FAILED); 73*7c478bd9Sstevel@tonic-gate } 74*7c478bd9Sstevel@tonic-gate *ppSrvURL = surl; 75*7c478bd9Sstevel@tonic-gate surl->s_pcSrvType = ""; 76*7c478bd9Sstevel@tonic-gate surl->s_pcNetFamily = ""; 77*7c478bd9Sstevel@tonic-gate surl->s_pcHost = ""; 78*7c478bd9Sstevel@tonic-gate surl->s_iPort = 0; 79*7c478bd9Sstevel@tonic-gate surl->s_pcSrvPart = ""; 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate /* parse type */ 82*7c478bd9Sstevel@tonic-gate p = strstr(pcSrvURL, ":/"); 83*7c478bd9Sstevel@tonic-gate if (!p) 84*7c478bd9Sstevel@tonic-gate goto error; 85*7c478bd9Sstevel@tonic-gate q = pcSrvURL; 86*7c478bd9Sstevel@tonic-gate *p++ = 0; p++; 87*7c478bd9Sstevel@tonic-gate r = strdup(q); 88*7c478bd9Sstevel@tonic-gate if (parseType(r, type) != SLP_OK) 89*7c478bd9Sstevel@tonic-gate goto error; 90*7c478bd9Sstevel@tonic-gate free(r); 91*7c478bd9Sstevel@tonic-gate /* no need to free type since it is on the stack */ 92*7c478bd9Sstevel@tonic-gate surl->s_pcSrvType = q; 93*7c478bd9Sstevel@tonic-gate 94*7c478bd9Sstevel@tonic-gate /* do we have a transport? */ 95*7c478bd9Sstevel@tonic-gate q = strchr(p, '/'); 96*7c478bd9Sstevel@tonic-gate if (!q) 97*7c478bd9Sstevel@tonic-gate goto error; 98*7c478bd9Sstevel@tonic-gate *q++ = 0; 99*7c478bd9Sstevel@tonic-gate if (!validateTransport(p)) 100*7c478bd9Sstevel@tonic-gate goto error; 101*7c478bd9Sstevel@tonic-gate surl->s_pcNetFamily = p; /* may be \0 */ 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate /* host part */ 104*7c478bd9Sstevel@tonic-gate /* do we have a port #? */ 105*7c478bd9Sstevel@tonic-gate p = strchr(q, ':'); 106*7c478bd9Sstevel@tonic-gate r = strchr(q, '/'); 107*7c478bd9Sstevel@tonic-gate if (!p && !r) { /* only host part */ 108*7c478bd9Sstevel@tonic-gate surl->s_pcHost = q; 109*7c478bd9Sstevel@tonic-gate return (SLP_OK); 110*7c478bd9Sstevel@tonic-gate } 111*7c478bd9Sstevel@tonic-gate if (p && !r) { /* host + port, no URL part */ 112*7c478bd9Sstevel@tonic-gate int port; 113*7c478bd9Sstevel@tonic-gate surl->s_pcHost = q; 114*7c478bd9Sstevel@tonic-gate *p++ = 0; 115*7c478bd9Sstevel@tonic-gate port = atoi(p); 116*7c478bd9Sstevel@tonic-gate if (port <= 0) 117*7c478bd9Sstevel@tonic-gate goto error; 118*7c478bd9Sstevel@tonic-gate surl->s_iPort = port; 119*7c478bd9Sstevel@tonic-gate return (SLP_OK); 120*7c478bd9Sstevel@tonic-gate } 121*7c478bd9Sstevel@tonic-gate *r++ = 0; 122*7c478bd9Sstevel@tonic-gate if (!p || p > r) { /* no port */ 123*7c478bd9Sstevel@tonic-gate surl->s_pcHost = q; 124*7c478bd9Sstevel@tonic-gate } else { /* host + port + url part */ 125*7c478bd9Sstevel@tonic-gate int port; 126*7c478bd9Sstevel@tonic-gate surl->s_pcHost = q; 127*7c478bd9Sstevel@tonic-gate *p++ = 0; 128*7c478bd9Sstevel@tonic-gate port = atoi(p); 129*7c478bd9Sstevel@tonic-gate if (port <= 0) 130*7c478bd9Sstevel@tonic-gate goto error; 131*7c478bd9Sstevel@tonic-gate surl->s_iPort = port; 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate /* r now points to the URL part */ 135*7c478bd9Sstevel@tonic-gate surl->s_pcSrvPart = r; 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate return (SLP_OK); 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate error: 140*7c478bd9Sstevel@tonic-gate free(surl); 141*7c478bd9Sstevel@tonic-gate *ppSrvURL = NULL; 142*7c478bd9Sstevel@tonic-gate return (SLP_PARSE_ERROR); 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate /* 146*7c478bd9Sstevel@tonic-gate * typeString contains only the service type part of an URL. It should 147*7c478bd9Sstevel@tonic-gate * point to a string which parseType can destructively modify. 148*7c478bd9Sstevel@tonic-gate */ 149*7c478bd9Sstevel@tonic-gate static SLPError parseType(char *typeString, slp_type_t *type) { 150*7c478bd9Sstevel@tonic-gate char *p, *q; 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate /* Initialize type structure */ 153*7c478bd9Sstevel@tonic-gate type->isServiceURL = SLP_FALSE; 154*7c478bd9Sstevel@tonic-gate type->atype = NULL; 155*7c478bd9Sstevel@tonic-gate type->ctype = NULL; 156*7c478bd9Sstevel@tonic-gate type->na = NULL; 157*7c478bd9Sstevel@tonic-gate type->orig = typeString; 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate if (!validateTypeChars(typeString)) 160*7c478bd9Sstevel@tonic-gate return (SLP_PARSE_ERROR); 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate /* Is this a service: URL? */ 163*7c478bd9Sstevel@tonic-gate p = strchr(typeString, ':'); 164*7c478bd9Sstevel@tonic-gate if (strncasecmp( 165*7c478bd9Sstevel@tonic-gate typeString, SERVICE_PREFIX, strlen(SERVICE_PREFIX)) == 0) { 166*7c478bd9Sstevel@tonic-gate type->isServiceURL = SLP_TRUE; 167*7c478bd9Sstevel@tonic-gate if (!p) 168*7c478bd9Sstevel@tonic-gate return (SLP_PARSE_ERROR); 169*7c478bd9Sstevel@tonic-gate *p++ = 0; 170*7c478bd9Sstevel@tonic-gate } else { 171*7c478bd9Sstevel@tonic-gate if (p) /* can't have an abstract type in a non-service url */ 172*7c478bd9Sstevel@tonic-gate return (SLP_PARSE_ERROR); 173*7c478bd9Sstevel@tonic-gate p = typeString; 174*7c478bd9Sstevel@tonic-gate } 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate /* p now points to the beginning of the type */ 177*7c478bd9Sstevel@tonic-gate /* is this an abstract type? */ 178*7c478bd9Sstevel@tonic-gate q = strchr(p, ':'); 179*7c478bd9Sstevel@tonic-gate if (q) { 180*7c478bd9Sstevel@tonic-gate type->atype = p; 181*7c478bd9Sstevel@tonic-gate *q++ = 0; 182*7c478bd9Sstevel@tonic-gate if (!*p) 183*7c478bd9Sstevel@tonic-gate return (SLP_PARSE_ERROR); 184*7c478bd9Sstevel@tonic-gate } else { q = p; } 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate /* q should now point to the concrete type */ 187*7c478bd9Sstevel@tonic-gate /* is there a naming authority? */ 188*7c478bd9Sstevel@tonic-gate p = strchr(q, '.'); 189*7c478bd9Sstevel@tonic-gate if (p) { 190*7c478bd9Sstevel@tonic-gate *p++ = 0; 191*7c478bd9Sstevel@tonic-gate if (!*p) 192*7c478bd9Sstevel@tonic-gate return (SLP_PARSE_ERROR); 193*7c478bd9Sstevel@tonic-gate type->na = p; 194*7c478bd9Sstevel@tonic-gate } 195*7c478bd9Sstevel@tonic-gate if (!*q) 196*7c478bd9Sstevel@tonic-gate return (SLP_PARSE_ERROR); 197*7c478bd9Sstevel@tonic-gate type->ctype = q; 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate return (SLP_OK); 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate static int validateTransport(char *t) { 203*7c478bd9Sstevel@tonic-gate if (*t == 0 || 204*7c478bd9Sstevel@tonic-gate strcasecmp(t, "ipx") == 0 || 205*7c478bd9Sstevel@tonic-gate strcasecmp(t, "at") == 0) 206*7c478bd9Sstevel@tonic-gate return (1); 207*7c478bd9Sstevel@tonic-gate return (0); 208*7c478bd9Sstevel@tonic-gate } 209*7c478bd9Sstevel@tonic-gate 210*7c478bd9Sstevel@tonic-gate static int checkURLString(char *s) { 211*7c478bd9Sstevel@tonic-gate int i; 212*7c478bd9Sstevel@tonic-gate size_t l = strlen(s); 213*7c478bd9Sstevel@tonic-gate for (i = 0; i < l; i++) { 214*7c478bd9Sstevel@tonic-gate if (isalnum(s[i]) || 215*7c478bd9Sstevel@tonic-gate s[i] == '/' || s[i] == ':' || s[i] == '-' || 216*7c478bd9Sstevel@tonic-gate s[i] == ':' || s[i] == '.' || s[i] == '%' || 217*7c478bd9Sstevel@tonic-gate s[i] == '_' || s[i] == '\''|| s[i] == '*' || 218*7c478bd9Sstevel@tonic-gate s[i] == '(' || s[i] == ')' || s[i] == '$' || 219*7c478bd9Sstevel@tonic-gate s[i] == '!' || s[i] == ',' || s[i] == '+' || 220*7c478bd9Sstevel@tonic-gate s[i] == '\\'|| s[i] == ';' || s[i] == '@' || 221*7c478bd9Sstevel@tonic-gate s[i] == '?' || s[i] == '&' || s[i] == '=') 222*7c478bd9Sstevel@tonic-gate continue; 223*7c478bd9Sstevel@tonic-gate return (0); 224*7c478bd9Sstevel@tonic-gate } 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate return (1); 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate static int validateTypeChars(char *s) { 231*7c478bd9Sstevel@tonic-gate int i; 232*7c478bd9Sstevel@tonic-gate size_t l = strlen(s); 233*7c478bd9Sstevel@tonic-gate for (i = 0; i < l; i++) 234*7c478bd9Sstevel@tonic-gate if (!isalnum(s[i]) && 235*7c478bd9Sstevel@tonic-gate s[i] != '-' && 236*7c478bd9Sstevel@tonic-gate s[i] != '+' && 237*7c478bd9Sstevel@tonic-gate s[i] != '.' && 238*7c478bd9Sstevel@tonic-gate s[i] != ':') 239*7c478bd9Sstevel@tonic-gate return (0); 240*7c478bd9Sstevel@tonic-gate return (1); 241*7c478bd9Sstevel@tonic-gate } 242