... | ... |
@@ -20,7 +20,8 @@ struct sip_uri { |
20 | 20 |
|
21 | 21 |
int parse_uri(char* buf, int len, struct sip_uri* uri) |
22 | 22 |
{ |
23 |
- enum states { URI_INIT, URI_USER, URI_PASSWORD, URI_HOST, URI_PORT, |
|
23 |
+ enum states { URI_INIT, URI_USER, URI_PASSWORD, URI_HOST, URI_HOST_P, |
|
24 |
+ URI_HOST6_P, URI_HOST6_END, URI_PORT, |
|
24 | 25 |
URI_PARAM, URI_HEADERS }; |
25 | 26 |
enum states state; |
26 | 27 |
char* s; |
... | ... |
@@ -54,8 +55,31 @@ int parse_uri(char* buf, int len, struct sip_uri* uri) |
54 | 55 |
found_user=1;\ |
55 | 56 |
error_headers=0; \ |
56 | 57 |
state=URI_HOST; \ |
57 |
- }else goto error_bad_char; |
|
58 |
- |
|
58 |
+ }else goto error_bad_char |
|
59 |
+#define check_host_end \ |
|
60 |
+ case ':': \ |
|
61 |
+ /* found the host */ \ |
|
62 |
+ uri->host.s=s; \ |
|
63 |
+ uri->host.len=p-s; \ |
|
64 |
+ state=URI_PORT; \ |
|
65 |
+ s=p+1; \ |
|
66 |
+ break; \ |
|
67 |
+ case ';': \ |
|
68 |
+ uri->host.s=s; \ |
|
69 |
+ uri->host.len=p-s; \ |
|
70 |
+ state=URI_PARAM; \ |
|
71 |
+ s=p+1; \ |
|
72 |
+ break; \ |
|
73 |
+ case '?': \ |
|
74 |
+ uri->host.s=s; \ |
|
75 |
+ uri->host.len=p-s; \ |
|
76 |
+ state=URI_HEADERS; \ |
|
77 |
+ s=p+1; \ |
|
78 |
+ break; \ |
|
79 |
+ case '&': \ |
|
80 |
+ case '@': \ |
|
81 |
+ goto error_bad_char |
|
82 |
+ |
|
59 | 83 |
end=buf+len; |
60 | 84 |
p=buf+4; |
61 | 85 |
found_user=0; |
... | ... |
@@ -69,9 +93,26 @@ int parse_uri(char* buf, int len, struct sip_uri* uri) |
69 | 93 |
(buf[3]==':') ) ) goto error_bad_uri; |
70 | 94 |
|
71 | 95 |
s=p; |
72 |
- state=URI_USER; |
|
73 | 96 |
for(;p<end; p++){ |
74 | 97 |
switch(state){ |
98 |
+ case URI_INIT: |
|
99 |
+ switch(*p){ |
|
100 |
+ case '[': |
|
101 |
+ /* uri = [ipv6address]... */ |
|
102 |
+ state=URI_HOST6_P; |
|
103 |
+ s=p; |
|
104 |
+ break; |
|
105 |
+ case ']': |
|
106 |
+ /* invalid, no uri can start with ']' */ |
|
107 |
+ case ':': |
|
108 |
+ /* the same as above for ':' */ |
|
109 |
+ goto error_bad_char; |
|
110 |
+ case '@': /* error no user part, or |
|
111 |
+ be forgiving and accept it ? */ |
|
112 |
+ default: |
|
113 |
+ state=URI_USER; |
|
114 |
+ } |
|
115 |
+ break; |
|
75 | 116 |
case URI_USER: |
76 | 117 |
switch(*p){ |
77 | 118 |
case '@': |
... | ... |
@@ -104,6 +145,9 @@ int parse_uri(char* buf, int len, struct sip_uri* uri) |
104 | 145 |
s=p+1; |
105 | 146 |
break; |
106 | 147 |
/* almost anything permitted in the user part */ |
148 |
+ case '[': |
|
149 |
+ case ']': /* the user part cannot contain "[]" */ |
|
150 |
+ goto error_bad_char; |
|
107 | 151 |
} |
108 | 152 |
break; |
109 | 153 |
case URI_PASSWORD: /* this can also be the port (missing user)*/ |
... | ... |
@@ -142,34 +186,50 @@ int parse_uri(char* buf, int len, struct sip_uri* uri) |
142 | 186 |
found_user=1; /* there is no user part */ |
143 | 187 |
s=p+1; |
144 | 188 |
break; |
189 |
+ case '[': |
|
190 |
+ case ']': |
|
145 | 191 |
case ':': |
146 | 192 |
goto error_bad_char; |
147 | 193 |
} |
148 | 194 |
break; |
149 | 195 |
case URI_HOST: |
150 | 196 |
switch(*p){ |
151 |
- case ':': |
|
152 |
- /* found the host */ |
|
153 |
- uri->host.s=s; |
|
154 |
- uri->host.len=p-s; |
|
155 |
- state=URI_PORT; |
|
156 |
- s=p+1; |
|
197 |
+ case '[': |
|
198 |
+ state=URI_HOST6_P; |
|
157 | 199 |
break; |
200 |
+ case ':': |
|
158 | 201 |
case ';': |
159 |
- uri->host.s=s; |
|
160 |
- uri->host.len=p-s; |
|
161 |
- state=URI_PARAM; |
|
162 |
- s=p+1; |
|
163 |
- break; |
|
164 |
- case '?': |
|
165 |
- uri->host.s=s; |
|
166 |
- uri->host.len=p-s; |
|
167 |
- state=URI_HEADERS; |
|
168 |
- s=p+1; |
|
202 |
+ case '?': /* null host name ->invalid */ |
|
203 |
+ case '&': |
|
204 |
+ case '@': /*chars not allowed in hosts names */ |
|
205 |
+ goto error_bad_host; |
|
206 |
+ default: |
|
207 |
+ state=URI_HOST_P; |
|
208 |
+ } |
|
209 |
+ break; |
|
210 |
+ case URI_HOST_P: |
|
211 |
+ switch(*p){ |
|
212 |
+ check_host_end; |
|
213 |
+ } |
|
214 |
+ break; |
|
215 |
+ case URI_HOST6_END: |
|
216 |
+ switch(*p){ |
|
217 |
+ check_host_end; |
|
218 |
+ default: /*no chars allowed after [ipv6] */ |
|
219 |
+ goto error_bad_host; |
|
220 |
+ } |
|
221 |
+ break; |
|
222 |
+ case URI_HOST6_P: |
|
223 |
+ switch(*p){ |
|
224 |
+ case ']': |
|
225 |
+ state=URI_HOST6_END; |
|
169 | 226 |
break; |
227 |
+ case '[': |
|
170 | 228 |
case '&': |
171 | 229 |
case '@': |
172 |
- goto error_bad_char; |
|
230 |
+ case ';': |
|
231 |
+ case '?': |
|
232 |
+ goto error_bad_host; |
|
173 | 233 |
} |
174 | 234 |
break; |
175 | 235 |
case URI_PORT: |
... | ... |
@@ -271,6 +331,8 @@ int parse_uri(char* buf, int len, struct sip_uri* uri) |
271 | 331 |
} |
272 | 332 |
/*end of uri */ |
273 | 333 |
switch (state){ |
334 |
+ case URI_INIT: /* error empy uri */ |
|
335 |
+ goto error_too_short; |
|
274 | 336 |
case URI_USER: |
275 | 337 |
/* this is the host, it can't be the user */ |
276 | 338 |
if (found_user) goto error_bad_uri; |
... | ... |
@@ -287,10 +349,14 @@ int parse_uri(char* buf, int len, struct sip_uri* uri) |
287 | 349 |
uri->user.s=0; |
288 | 350 |
uri->user.len=0; |
289 | 351 |
break; |
290 |
- case URI_HOST: |
|
352 |
+ case URI_HOST_P: |
|
353 |
+ case URI_HOST6_END: |
|
291 | 354 |
uri->host.s=s; |
292 | 355 |
uri->host.len=p-s; |
293 | 356 |
break; |
357 |
+ case URI_HOST: /* error: null host */ |
|
358 |
+ case URI_HOST6_P: /* error: unterminated ipv6 reference*/ |
|
359 |
+ goto error_bad_host; |
|
294 | 360 |
case URI_PORT: |
295 | 361 |
uri->port.s=s; |
296 | 362 |
uri->port.len=p-s; |
... | ... |
@@ -329,6 +395,11 @@ error_bad_char: |
329 | 395 |
" parsed: <%.*s> (%d) / <%.*s> (%d)\n", |
330 | 396 |
*p, state, (p-buf), buf, (p-buf), len, buf, len); |
331 | 397 |
return -1; |
398 |
+error_bad_host: |
|
399 |
+ LOG(L_ERR, "ERROR: parse_uri: bad host in uri (error at char %c in" |
|
400 |
+ " state %d) parsed: <%.*s>(%d) /<%.*s> (%d)\n", |
|
401 |
+ *p, state, (p-buf), buf, (p-buf), len, buf, len); |
|
402 |
+ return -1; |
|
332 | 403 |
error_bad_uri: |
333 | 404 |
LOG(L_ERR, "ERROR: parse_uri: bad uri, state %d" |
334 | 405 |
" parsed: <%.*s> (%d) / <%.*s> (%d)\n", |