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