Browse code

Identity-info and Identity header parser does not insist on BNF specified in RFC.

Memory allocator part of Identity-info, Identity and Date header moved out
from get_hdr_field()@parser/msg_parser.c

Gergely Kovacs authored on 15/10/2007 14:32:19
Showing 3 changed files
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- * $Id$ 
2
+ * $Id$
3 3
  *
4 4
  * Copyright (c) 2007 iptelorg GmbH
5 5
  *
... ...
@@ -140,46 +140,59 @@ static int rfc1123totm (char *stime, struct tm *ttm ) {
140 140
 	return 0;
141 141
 }
142 142
 
143
-char* parse_date(char *buffer, char *end, struct date_body *db)
143
+void parse_date(char *buffer, char *end, struct date_body *db)
144 144
 {
145
-	char *p;
146
-	int i1;
147
-
148 145
 	db->error=PARSE_ERROR;
149
-	p = buffer;
150 146
 
151 147
 	/* check whether enough characters are available */
152
-	for (i1 = 0; i1 < RFC1123DATELENGTH || p[i1] == '\n' || p + i1 >= end;i1++);
153
-	if (i1 < RFC1123DATELENGTH)
148
+	if (end - buffer < RFC1123DATELENGTH)
154 149
 		goto error;
155 150
 
156 151
 	if (rfc1123totm(buffer,&db->date))
157 152
 		goto error;
158 153
 
159
-	p+=RFC1123DATELENGTH;
154
+	db->error=PARSE_OK;
155
+	return ;
156
+error:
157
+	LOG(L_ERR,"ERROR: parse_date: parse error\n");
158
+	return ;
159
+}
160 160
 
161
-	p=eat_lws_end(p, end);
162
-	/*check if the header ends here*/
163
-	if (p>=end) {
164
-		LOG(L_ERR, "ERROR: parse_date: strange EoHF\n");
161
+int parse_date_header(struct sip_msg *msg)
162
+{
163
+	struct date_body* date_b;
164
+
165
+
166
+	if ( !msg->date && (parse_headers(msg,HDR_DATE_F,0)==-1 || !msg->date) ) {
167
+		LOG(L_ERR,"ERROR:parse_date_header: bad msg or missing DATE header\n");
165 168
 		goto error;
166 169
 	}
167
-	if (*p=='\r' && p+1<end && *(p+1)=='\n') {
168
-		db->error=PARSE_OK;
169
-		return p+2;
170
+
171
+	/* maybe the header is already parsed! */
172
+	if (msg->date->parsed)
173
+		return 0;
174
+
175
+	date_b=pkg_malloc(sizeof(*date_b));
176
+	if (date_b==0){
177
+		LOG(L_ERR, "ERROR:parse_date_header: out of memory\n");
178
+		goto error;
170 179
 	}
171
-	if (*p=='\n') {
172
-		db->error=PARSE_OK;
173
-		return p+1;
180
+	memset(date_b, 0, sizeof(*date_b));
181
+
182
+	parse_date(msg->date->body.s,
183
+			   msg->date->body.s + msg->date->body.len+1,
184
+			   date_b);
185
+	if (date_b->error==PARSE_ERROR){
186
+		free_date(date_b);
187
+		goto error;
174 188
 	}
175
-	LOG(L_ERR, "ERROR: Date EoL expected\n");
189
+	msg->date->parsed=(void*)date_b;
190
+
191
+	return 0;
176 192
 error:
177
-	LOG(L_ERR,"ERROR: parse_date: parse error: \"%.*s\" (%d)\n",
178
-				i1, buffer, i1);
179
-	return p;
193
+	return -1;
180 194
 }
181 195
 
182
-
183 196
 void free_date(struct date_body *db)
184 197
 {
185 198
 	pkg_free(db);
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- * $Id$ 
2
+ * $Id$
3 3
  *
4 4
  * Copyright (c) 2007 iptelorg GmbH
5 5
  *
... ...
@@ -37,136 +37,144 @@
37 37
  * Parse Identity header field
38 38
  */
39 39
 
40
+#define SP(_c) ((_c)=='\t' || (_c)==' ')
41
+inline static int isendofhash (char* p, char* end)
42
+{
43
+	/* new header line */
44
+	if ((p<end && *p=='"')
45
+		/* end of message */
46
+		|| ((*p=='\n' || *p=='\r') && p+1==end))
47
+		return 1;
48
+	else
49
+		return 0;
50
+}
51
+
52
+
40 53
 /*
41 54
  * If the value of Identity header contains any LWS then we've to create
42 55
  * a new buffer and move there the LWSless part
43 56
  */
44
-int movetomybuffer (char *buffer, char *end, char *p, struct identity_body *ib)
57
+int movetomybuffer (char *pstart,
58
+					char *pend,
59
+					char *pcur,
60
+					struct identity_body *ib)
45 61
 {
46
-	char *bufend;
62
+	char *phashend;
47 63
 
48
-	if (!(bufend=q_memchr(p, '"', end-p))) {
49
-		LOG(L_ERR, "parse_identity: quotation mark is missing\n");
50
-		return -1;
51
-	}
64
+	for (phashend = pcur; !isendofhash(phashend, pend); phashend++);
52 65
 
53
-	if (!(ib->hash.s=pkg_malloc(bufend-buffer))) {
66
+	if (!(ib->hash.s=pkg_malloc(phashend-pstart))) {
54 67
 		LOG(L_ERR, "parse_identity: out of memory\n");
55 68
 		return -2;
56 69
 	}
57 70
 	ib->ballocated=1;
58 71
 
59
-	memcpy(ib->hash.s, buffer, ib->hash.len);
72
+	memcpy(ib->hash.s, pstart, ib->hash.len);
60 73
 
61 74
 	return 0;
62 75
 }
63 76
 
64
-char* parse_identity(char *buffer, char* end, struct identity_body* ib)
77
+
78
+void parse_identity(char *buffer, char* end, struct identity_body* ib)
65 79
 {
66
-	char *p=NULL;
67
-	char bpadded=0;
80
+	char *p=NULL, *pstart=NULL;
68 81
 
69 82
 	if (!buffer || !end || !ib)
70 83
 		goto error;
71 84
 
72 85
 	ib->error=PARSE_ERROR;
73 86
 
74
-	/* there must be '"' sign because there might be '=' sign in the
75
-	 * value of Identity header
76
-	 */
77
-	if (*buffer != '"') {
78
-		LOG(L_ERR, "parse_identity: quotation mark is missing\n");
79
-		goto error;
80
-	}
87
+	/* if there is a '"' sign then we'll step over it */
88
+	*buffer == '"' ? (pstart = buffer + 1) : (pstart = buffer);
81 89
 
82
-	/* we step over the '"' mark */
83
-	ib->hash.s=buffer+1;
90
+	ib->hash.s=pstart;
84 91
 	ib->hash.len=0;
85 92
 
86
-	for (p=buffer+1; p < end && *p != '"'; p++) {
93
+	for (p = pstart; p < end; p++) {
87 94
 		/* check the BASE64 alphabet */
88
-		if (!bpadded
89
-		    && ((*p >= 'a' && *p <='z')
90
-			 	|| (*p >= 'A' && *p <='Z')
91
-				|| (*p >= '0' && *p <='9')
92
-				|| (*p == '+' || *p == '/'))) {
95
+		if (((*p >= 'a' && *p <='z')
96
+			|| (*p >= 'A' && *p <='Z')
97
+			|| (*p >= '0' && *p <='9')
98
+			|| (*p == '+' || *p == '/' || *p == '='))) {
93 99
 			if (ib->ballocated)
94 100
 				ib->hash.s[ib->hash.len]=*p;
95 101
 			ib->hash.len++;
96 102
 			continue;
97 103
 		}
98 104
 
99
-		/* check the BASE64 padding */
100
-		if ((p+1 < end && *p == '=' && *(p+1) != '=')
101
-		    || (p+2 < end && *p == '=' && *(p+1) == '=' && *(p+2) != '=')) {
102
-			bpadded=1;
103
-			if (ib->ballocated)
104
-				ib->hash.s[ib->hash.len]=*p;
105
-			ib->hash.len++;
106
-			continue;
107
-		}
108
-
109
-		/* LSW case */
110
-		if (*p == ' ' || *p == '\t') {
111
-			for (p++; p < end && (*p == ' ' || *p == '\t'); p++);
112
-			if (p == end)
113
-				goto parseerror;
114
-			/* we've to create another whitespaceless buffer */
115
-			if (!ib->ballocated && (movetomybuffer(buffer+1, end, p-1, ib)))
105
+		/* LWS */
106
+		if (*p=='\n' && p+1<end && SP(*(p+1))) {
107
+			/* p - 1 because we don't want to pass '\n' */
108
+			if (!ib->ballocated && (movetomybuffer(pstart, end, p-1, ib)))
116 109
 				goto error;
117
-		}
118
-		if (p+2 < end && *p == '\n' && *(p+1) == ' '
119
-		    && !(*(p+2) == ' ' || *(p+2) == '\t')) {
120
-			/* we've to create another whitespaceless buffer */
121
-			if (!ib->ballocated && (movetomybuffer(buffer+1, end, p-1, ib)))
122
-				goto error;
123
-			p+=1;
110
+			/* p + 1 < end because 'continue' increases p so we'd skip \n
111
+			   we need after this for loop */
112
+			for (p+=1; p + 1 < end && SP(*(p + 1)); p++);
124 113
 			continue;
125 114
 		}
126
-		if (p+3 < end && *p == '\r' && *(p+1) == '\n' && *(p+2) == ' '
127
-		  	&& !(*(p+3) == ' ' || *(p+3) == '\t')) {
128
-			/* we've to create another whitespaceless buffer */
129
-			if (!ib->ballocated && (movetomybuffer(buffer+1, end, p-1, ib)))
115
+		if (*p=='\r' && p+2<end && *(p+1)=='\n' && SP(*(p+2))) {
116
+			if (!ib->ballocated && (movetomybuffer(pstart, end, p-1, ib)))
130 117
 				goto error;
131
-			p+=2;
118
+			for (p+=2; p + 1 < end && SP(*(p + 1)); p++);
132 119
 			continue;
133 120
 		}
134 121
 
122
+		if (isendofhash(p, end))
123
+			break;
124
+
135 125
 		/* parse error */
136
-		break;
137
-	}
138
-	if (p == end || *p != '"')
139 126
 		goto parseerror;
127
+	}
140 128
 
141
-	/* we step over '"' */
142
-	p++;
129
+	/* this is the final quotation mark so we step over */
130
+	ib->error=PARSE_OK;
131
+	return ;
143 132
 
144
-	p=eat_lws_end(p, end);
145
-	/*check if the header ends here*/
146
-	if (p>=end) {
147
-		LOG(L_ERR, "ERROR: parse_identity: strange EoHF\n");
133
+parseerror:
134
+	LOG( L_ERR , "ERROR: parse_identity: "
135
+		"unexpected char [0x%X]: <<%.*s>> .\n",
136
+		*p,(int)(p-buffer), ZSW(buffer));
137
+error:
138
+	return ;
139
+}
140
+
141
+int parse_identity_header(struct sip_msg *msg)
142
+{
143
+	struct identity_body* identity_b;
144
+
145
+
146
+	if ( !msg->identity
147
+		 && (parse_headers(msg,HDR_IDENTITY_F,0)==-1
148
+		 || !msg->identity) ) {
149
+		LOG(L_ERR,"ERROR:parse_identity_header: bad msg or missing IDENTITY header\n");
148 150
 		goto error;
149 151
 	}
150
-	if (*p=='\r' && p+1<end && *(p+1)=='\n') {
151
-		ib->error=PARSE_OK;
152
-		return p+2;
152
+
153
+	/* maybe the header is already parsed! */
154
+	if (msg->identity->parsed)
155
+		return 0;
156
+
157
+	identity_b=pkg_malloc(sizeof(*identity_b));
158
+	if (identity_b==0){
159
+		LOG(L_ERR, "ERROR:parse_identity_header: out of memory\n");
160
+		goto error;
153 161
 	}
154
-	if (*p=='\n') {
155
-		ib->error=PARSE_OK;
156
-		return p+1;
162
+	memset(identity_b, 0, sizeof(*identity_b));
163
+
164
+	parse_identity(msg->identity->body.s,
165
+				   msg->identity->body.s + msg->identity->body.len+1,
166
+				   identity_b);
167
+	if (identity_b->error==PARSE_ERROR){
168
+		free_identity(identity_b);
169
+		goto error;
157 170
 	}
158
-	LOG(L_ERR, "ERROR: Identity EoL expected\n");
159
-	goto error;
171
+	msg->identity->parsed=(void*)identity_b;
160 172
 
161
-parseerror:
162
-	LOG( L_ERR , "ERROR: parse_identity: "
163
-		"unexpected char [%c]: <<%.*s>> .\n",
164
-		*p,(int)(p-buffer), ZSW(buffer));
173
+	return 0;
165 174
 error:
166
-	return p;
175
+	return -1;
167 176
 }
168 177
 
169
-
170 178
 void free_identity(struct identity_body *ib)
171 179
 {
172 180
 	if (ib->ballocated)
... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- * $Id$ 
2
+ * $Id$
3 3
  *
4 4
  * Copyright (c) 2007 iptelorg GmbH
5 5
  *
... ...
@@ -34,14 +34,15 @@
34 34
 #include "parser_f.h"  /* eat_space_end and so on */
35 35
 
36 36
 
37
-char* parse_identityinfo(char *buffer, char *end, struct identityinfo_body *ii_b)
37
+void parse_identityinfo(char *buffer, char *end, struct identityinfo_body *ii_b)
38 38
 {
39 39
 	int status = II_START;
40 40
 	int mainstatus = II_M_START;
41 41
 	char *p;
42 42
 
43 43
 
44
-	if (!buffer || !end || !ii_b) return NULL;
44
+	if (!buffer || !end || !ii_b) return ;
45
+
45 46
 
46 47
 	ii_b->error = PARSE_ERROR;
47 48
 
... ...
@@ -56,35 +57,38 @@ char* parse_identityinfo(char *buffer, char *end, struct identityinfo_body *ii_b
56 56
 					goto parseerror;
57 57
 					break;
58 58
 			case 'h':
59
-				case 'H': /* "http://" or "https://" part  */
60
-					switch (status) {
61
-						case II_URI_BEGIN:
62
-							if (end - p <= 8 || strncasecmp(p,"http",strlen("http")))
63
-								goto parseerror;
64
-							p+=4;
65
-							if (*p == 's' || *p == 'S') p++;
66
-							if (memcmp(p,"://",strlen("://")))
67
-								goto parseerror;
68
-							p+=2;
69
-							status = II_URI_DOMAIN;
70
-							break;
71
-						case II_URI_DOMAIN:
72
-							status = II_URI_IPV4;
73
-						case II_URI_IPV4:
74
-						case II_URI_IPV6:
75
-						case II_URI_PATH:
76
-						case II_TOKEN:
77
-						case II_TAG:
78
-							break;
79
-						case II_EQUAL:
80
-							status = II_TOKEN;
81
-							mainstatus = II_M_TOKEN;
82
-							ii_b->alg.s = p;
83
-							break;
84
-						default:
59
+			case 'H': /* "http://" or "https://" part  */
60
+				switch (status) {
61
+					case II_URI_BEGIN:
62
+						if (end - p <= 8 || strncasecmp(p,"http",strlen("http")))
85 63
 							goto parseerror;
86
-					}
87
-					break;
64
+						p+=4;
65
+						if (*p == 's' || *p == 'S') p++;
66
+						if (memcmp(p,"://",strlen("://")))
67
+							goto parseerror;
68
+						p+=2;
69
+						status = II_URI_DOMAIN;
70
+						break;
71
+					case II_URI_DOMAIN:
72
+						status = II_URI_IPV4;
73
+					case II_URI_IPV4:
74
+					case II_URI_IPV6:
75
+					case II_URI_PATH:
76
+					case II_TOKEN:
77
+					case II_TAG:
78
+						break;
79
+					case II_EQUAL:
80
+						status = II_TOKEN;
81
+						mainstatus = II_M_TOKEN;
82
+						ii_b->alg.s = p;
83
+						break;
84
+					case II_LWSCRLF:
85
+						ii_b->error=PARSE_OK;
86
+						return ;
87
+					default:
88
+						goto parseerror;
89
+				}
90
+				break;
88 91
 			case '/':
89 92
 				switch(status){
90 93
 					case II_URI_IPV4:
... ...
@@ -105,7 +109,7 @@ char* parse_identityinfo(char *buffer, char *end, struct identityinfo_body *ii_b
105 105
 					mainstatus = II_M_URI_END;
106 106
 				} else
107 107
 					goto parseerror;
108
-					break;
108
+				break;
109 109
 			case ' ':
110 110
 			case '\t':
111 111
 				switch (status) {
... ...
@@ -116,6 +120,7 @@ char* parse_identityinfo(char *buffer, char *end, struct identityinfo_body *ii_b
116 116
 						status = II_LWS;
117 117
 						break;
118 118
 					case II_LWS:
119
+					case II_LWSCRLFSP:
119 120
 						break;
120 121
 					case II_LWSCRLF:
121 122
 						status = II_LWSCRLFSP;
... ...
@@ -137,12 +142,18 @@ char* parse_identityinfo(char *buffer, char *end, struct identityinfo_body *ii_b
137 137
 					case II_LWS:
138 138
 						status = II_LWSCR;
139 139
 						break;
140
+					case II_LWSCRLF:
141
+						ii_b->error=PARSE_OK;
142
+						return ;
140 143
 					default:
141 144
 						goto parseerror;
142 145
 				}
143 146
 				break;
144 147
 			case '\n':
145 148
 				switch (status) {
149
+					case II_LWSCRLF:
150
+						ii_b->error=PARSE_OK;
151
+						return ;
146 152
 					case II_EQUAL:
147 153
 					case II_TAG:
148 154
 					case II_SEMIC:
... ...
@@ -151,26 +162,17 @@ char* parse_identityinfo(char *buffer, char *end, struct identityinfo_body *ii_b
151 151
 					case II_LWSCR:
152 152
 						status = II_LWSCRLF;
153 153
 						break;
154
-						case II_TOKEN: /* if there was not '\r' */
155
-							ii_b->alg.len = p - ii_b->alg.s;
154
+					case II_TOKEN: /* if there was not '\r' */
155
+						ii_b->alg.len = p - ii_b->alg.s;
156 156
 					case II_ENDHEADER:
157 157
 						p=eat_lws_end(p, end);
158 158
 						/*check if the header ends here*/
159 159
 						if (p>=end) {
160
-							LOG(L_ERR, "ERROR: parse_date: strange EoHF\n");
160
+							LOG(L_ERR, "ERROR: parse_identityinfo: strange EoHF\n");
161 161
 							goto parseerror;
162 162
 						}
163
-						if (*p=='\r' && p+1<end && *(p+1)=='\n') {
164
-							ii_b->error=PARSE_OK;
165
-							return p+2;
166
-						}
167
-						if (*p=='\n') {
168
-							ii_b->error=PARSE_OK;
169
-							return p+1;
170
-						}
171
-						LOG(L_ERR, "ERROR: Date EoL expected\n");
172
-						goto error;
173
-						break;
163
+						ii_b->error=PARSE_OK;
164
+						return ;
174 165
 					default:
175 166
 						goto parseerror;
176 167
 				}
... ...
@@ -190,7 +192,7 @@ char* parse_identityinfo(char *buffer, char *end, struct identityinfo_body *ii_b
190 190
 						goto parseerror;
191 191
 				}
192 192
 				break;
193
-				case 'a': /* tag part of 'alg' parameter */
193
+			case 'a': /* tag part of 'alg' parameter */
194 194
 			case 'A':
195 195
 				switch (status) {
196 196
 					case II_LWS:
... ...
@@ -217,6 +219,9 @@ char* parse_identityinfo(char *buffer, char *end, struct identityinfo_body *ii_b
217 217
 						mainstatus = II_M_TOKEN;
218 218
 						ii_b->alg.s = p;
219 219
 						break;
220
+					case II_LWSCRLF:
221
+						ii_b->error=PARSE_OK;
222
+						return ;
220 223
 					default:
221 224
 						goto parseerror;
222 225
 				}
... ...
@@ -279,6 +284,9 @@ char* parse_identityinfo(char *buffer, char *end, struct identityinfo_body *ii_b
279 279
 						break;
280 280
 					case II_TOKEN:
281 281
 						break;
282
+					case II_LWSCRLF:
283
+						ii_b->error=PARSE_OK;
284
+						return ;
282 285
 					case II_URI_DOMAIN:
283 286
 						ii_b->domain.s = p;
284 287
 						status = II_URI_IPV4;
... ...
@@ -288,22 +296,60 @@ char* parse_identityinfo(char *buffer, char *end, struct identityinfo_body *ii_b
288 288
 						    || *p == '-'
289 289
 						    || *p == '.'
290 290
 						    || *p == ':' )
291
-							break;
291
+						break;
292 292
 					case II_START:
293 293
 						goto parseerror;
294 294
 				}
295 295
 				break;
296 296
 		}
297 297
 	}
298
+	/* we successfully parse the header */
299
+	ii_b->error=PARSE_OK;
300
+	return ;
298 301
 
299 302
 parseerror:
300
-		LOG( L_ERR , "ERROR: parse_identityinfo: "
301
-		"unexpected char [%c] in status %d: <<%.*s>> .\n",
302
-		*p,status, (int)(p-buffer), ZSW(buffer));
303
-error:
304
-		return p;
303
+	LOG( L_ERR , "ERROR: parse_identityinfo: "
304
+	"unexpected char [%c] in status %d: <<%.*s>> .\n",
305
+	*p,status, (int)(p-buffer), ZSW(p));
306
+	return ;
305 307
 }
306 308
 
309
+int parse_identityinfo_header(struct sip_msg *msg)
310
+{
311
+	struct identityinfo_body* identityinfo_b;
312
+
313
+
314
+	if ( !msg->identity_info
315
+		 && (parse_headers(msg,HDR_IDENTITY_INFO_F,0)==-1
316
+			 || !msg->identity_info) ) {
317
+		LOG(L_ERR,"ERROR:parse_identityinfo_header: bad msg or missing IDENTITY-INFO header\n");
318
+		goto error;
319
+	}
320
+
321
+	/* maybe the header is already parsed! */
322
+	if (msg->identity_info->parsed)
323
+		return 0;
324
+
325
+	identityinfo_b=pkg_malloc(sizeof(*identityinfo_b));
326
+	if (identityinfo_b==0){
327
+		LOG(L_ERR, "ERROR:parse_identityinfo_header: out of memory\n");
328
+		goto error;
329
+	}
330
+	memset(identityinfo_b, 0, sizeof(*identityinfo_b));
331
+
332
+	parse_identityinfo(msg->identity_info->body.s,
333
+					   msg->identity_info->body.s + msg->identity_info->body.len+1,
334
+					   identityinfo_b);
335
+	if (identityinfo_b->error==PARSE_ERROR){
336
+		free_identityinfo(identityinfo_b);
337
+		goto error;
338
+	}
339
+	msg->identity_info->parsed=(void*)identityinfo_b;
340
+
341
+	return 0;
342
+error:
343
+	return -1;
344
+}
307 345
 
308 346
 void free_identityinfo(struct identityinfo_body *ii_b)
309 347
 {