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
SLPParseSrvURL(char * pcSrvURL,SLPSrvURL ** ppSrvURL)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 */
parseType(char * typeString,slp_type_t * type)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
validateTransport(char * t)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
checkURLString(char * s)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
validateTypeChars(char * s)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