xref: /illumos-gate/usr/src/lib/libslp/clib/SLPParseSrvURL.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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