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 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <ctype.h> 32 #include <string.h> 33 #include <syslog.h> 34 #include <slp-internal.h> 35 36 /* 37 * URL parsing 38 */ 39 40 #define SLP_IANA "iana" 41 #define SERVICE_PREFIX "service" 42 43 /* service type struct */ 44 typedef struct slp_type { 45 SLPBoolean isServiceURL; 46 char *atype; 47 char *ctype; 48 char *na; 49 char *orig; 50 } slp_type_t; 51 52 static SLPError parseType(char *, slp_type_t *); 53 static int validateTypeChars(char *); 54 static int validateTransport(char *); 55 static int checkURLString(char *); 56 57 SLPError SLPParseSrvURL(char *pcSrvURL, SLPSrvURL** ppSrvURL) { 58 char *p, *q, *r; 59 SLPSrvURL *surl; 60 slp_type_t type[1]; 61 62 if (!pcSrvURL || !ppSrvURL) { 63 return (SLP_PARAMETER_BAD); 64 } 65 66 *ppSrvURL = NULL; 67 if (!checkURLString((char *)pcSrvURL)) 68 return (SLP_PARSE_ERROR); 69 70 if (!(surl = malloc(sizeof (*surl)))) { 71 slp_err(LOG_CRIT, 0, "SLPParseSrvURL", "out of memory"); 72 return (SLP_MEMORY_ALLOC_FAILED); 73 } 74 *ppSrvURL = surl; 75 surl->s_pcSrvType = ""; 76 surl->s_pcNetFamily = ""; 77 surl->s_pcHost = ""; 78 surl->s_iPort = 0; 79 surl->s_pcSrvPart = ""; 80 81 /* parse type */ 82 p = strstr(pcSrvURL, ":/"); 83 if (!p) 84 goto error; 85 q = pcSrvURL; 86 *p++ = 0; p++; 87 r = strdup(q); 88 if (parseType(r, type) != SLP_OK) 89 goto error; 90 free(r); 91 /* no need to free type since it is on the stack */ 92 surl->s_pcSrvType = q; 93 94 /* do we have a transport? */ 95 q = strchr(p, '/'); 96 if (!q) 97 goto error; 98 *q++ = 0; 99 if (!validateTransport(p)) 100 goto error; 101 surl->s_pcNetFamily = p; /* may be \0 */ 102 103 /* host part */ 104 /* do we have a port #? */ 105 p = strchr(q, ':'); 106 r = strchr(q, '/'); 107 if (!p && !r) { /* only host part */ 108 surl->s_pcHost = q; 109 return (SLP_OK); 110 } 111 if (p && !r) { /* host + port, no URL part */ 112 int port; 113 surl->s_pcHost = q; 114 *p++ = 0; 115 port = atoi(p); 116 if (port <= 0) 117 goto error; 118 surl->s_iPort = port; 119 return (SLP_OK); 120 } 121 *r++ = 0; 122 if (!p || p > r) { /* no port */ 123 surl->s_pcHost = q; 124 } else { /* host + port + url part */ 125 int port; 126 surl->s_pcHost = q; 127 *p++ = 0; 128 port = atoi(p); 129 if (port <= 0) 130 goto error; 131 surl->s_iPort = port; 132 } 133 134 /* r now points to the URL part */ 135 surl->s_pcSrvPart = r; 136 137 return (SLP_OK); 138 139 error: 140 free(surl); 141 *ppSrvURL = NULL; 142 return (SLP_PARSE_ERROR); 143 } 144 145 /* 146 * typeString contains only the service type part of an URL. It should 147 * point to a string which parseType can destructively modify. 148 */ 149 static SLPError parseType(char *typeString, slp_type_t *type) { 150 char *p, *q; 151 152 /* Initialize type structure */ 153 type->isServiceURL = SLP_FALSE; 154 type->atype = NULL; 155 type->ctype = NULL; 156 type->na = NULL; 157 type->orig = typeString; 158 159 if (!validateTypeChars(typeString)) 160 return (SLP_PARSE_ERROR); 161 162 /* Is this a service: URL? */ 163 p = strchr(typeString, ':'); 164 if (strncasecmp( 165 typeString, SERVICE_PREFIX, strlen(SERVICE_PREFIX)) == 0) { 166 type->isServiceURL = SLP_TRUE; 167 if (!p) 168 return (SLP_PARSE_ERROR); 169 *p++ = 0; 170 } else { 171 if (p) /* can't have an abstract type in a non-service url */ 172 return (SLP_PARSE_ERROR); 173 p = typeString; 174 } 175 176 /* p now points to the beginning of the type */ 177 /* is this an abstract type? */ 178 q = strchr(p, ':'); 179 if (q) { 180 type->atype = p; 181 *q++ = 0; 182 if (!*p) 183 return (SLP_PARSE_ERROR); 184 } else { q = p; } 185 186 /* q should now point to the concrete type */ 187 /* is there a naming authority? */ 188 p = strchr(q, '.'); 189 if (p) { 190 *p++ = 0; 191 if (!*p) 192 return (SLP_PARSE_ERROR); 193 type->na = p; 194 } 195 if (!*q) 196 return (SLP_PARSE_ERROR); 197 type->ctype = q; 198 199 return (SLP_OK); 200 } 201 202 static int validateTransport(char *t) { 203 if (*t == 0 || 204 strcasecmp(t, "ipx") == 0 || 205 strcasecmp(t, "at") == 0) 206 return (1); 207 return (0); 208 } 209 210 static int checkURLString(char *s) { 211 int i; 212 size_t l = strlen(s); 213 for (i = 0; i < l; i++) { 214 if (isalnum(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 s[i] == '\\'|| s[i] == ';' || s[i] == '@' || 221 s[i] == '?' || s[i] == '&' || s[i] == '=') 222 continue; 223 return (0); 224 } 225 226 return (1); 227 } 228 229 230 static int validateTypeChars(char *s) { 231 int i; 232 size_t l = strlen(s); 233 for (i = 0; i < l; i++) 234 if (!isalnum(s[i]) && 235 s[i] != '-' && 236 s[i] != '+' && 237 s[i] != '.' && 238 s[i] != ':') 239 return (0); 240 return (1); 241 } 242