Rev 29 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 29 | Rev 36 | ||
---|---|---|---|
1 | #! /bin/sh /usr/share/dpatch/dpatch-run |
1 | #! /bin/sh /usr/share/dpatch/dpatch-run |
2 | ## 50_permanent_include_errors.dpatch by Shevek <shevek@anarres.org>, edited by Magnus Holmgren |
2 | ## 50_permanent_include_errors.dpatch by Shevek <shevek@anarres.org>, edited by Magnus Holmgren |
3 | ## |
3 | ## |
4 | ## DP: Fix CVE-2008-2469 - buffer overflows handling DNS responses. |
4 | ## DP: Fix CVE-2008-2469 - buffer overflows handling DNS responses. |
5 | 5 | ||
6 | @DPATCH@ |
6 | @DPATCH@ |
7 | 7 | ||
8 | --- libspf2/src/libspf2/spf_dns_resolv.c.orig 2008-09-20 19:36:57.000000000 +0200 |
8 | --- libspf2/src/libspf2/spf_dns_resolv.c.orig 2008-09-20 19:36:57.000000000 +0200 |
9 | +++ libspf2/src/libspf2/spf_dns_resolv.c 2008-09-20 19:39:08.000000000 +0200 |
9 | +++ libspf2/src/libspf2/spf_dns_resolv.c 2008-09-20 19:39:08.000000000 +0200 |
10 | @@ -110,7 +110,8 @@ |
10 | @@ -110,7 +110,8 @@ |
11 | int nrec; |
11 | int nrec; |
12 | int cnt; |
12 | int cnt; |
13 | 13 | ||
14 | - u_char response[2048]; |
14 | - u_char response[2048]; |
15 | + u_char *responsebuf; |
15 | + u_char *responsebuf; |
16 | + size_t responselen; |
16 | + size_t responselen; |
17 | 17 | ||
18 | int dns_len; |
18 | int dns_len; |
19 | 19 | ||
20 | @@ -127,11 +128,13 @@ |
20 | @@ -127,11 +128,13 @@ |
21 | char name_buf[ NS_MAXDNAME ]; |
21 | char name_buf[ NS_MAXDNAME ]; |
22 | int prio; |
22 | int prio; |
23 | 23 | ||
24 | - int rdlen; |
24 | - int rdlen; |
25 | - const u_char *rdata, *rdata_end; |
25 | - const u_char *rdata, *rdata_end; |
26 | + size_t rdlen; |
26 | + size_t rdlen; |
27 | + const u_char *rdata; |
27 | + const u_char *rdata; |
28 | 28 | ||
29 | +#if HAVE_DECL_RES_NINIT |
29 | +#if HAVE_DECL_RES_NINIT |
30 | void *res_spec; |
30 | void *res_spec; |
31 | struct __res_state *res_state; |
31 | struct __res_state *res_state; |
32 | +#endif |
32 | +#endif |
33 | 33 | ||
34 | SPF_ASSERT_NOTNULL(spf_dns_server); |
34 | SPF_ASSERT_NOTNULL(spf_dns_server); |
35 | 35 | ||
36 | @@ -140,10 +143,12 @@ |
36 | @@ -140,10 +143,12 @@ |
37 | SPF_ASSERT_NOTNULL(spfhook); |
37 | SPF_ASSERT_NOTNULL(spfhook); |
38 | #endif |
38 | #endif |
39 | 39 | ||
40 | +#if HAVE_DECL_RES_NINIT |
40 | +#if HAVE_DECL_RES_NINIT |
41 | res_spec = pthread_getspecific(res_state_key); |
41 | res_spec = pthread_getspecific(res_state_key); |
42 | if (res_spec == NULL) { |
42 | if (res_spec == NULL) { |
43 | res_state = (struct __res_state *) |
43 | res_state = (struct __res_state *) |
44 | malloc(sizeof(struct __res_state)); |
44 | malloc(sizeof(struct __res_state)); |
45 | + memset(res_state, 0, sizeof(struct __res_state)); |
45 | + memset(res_state, 0, sizeof(struct __res_state)); |
46 | if (res_ninit(res_state) != 0) { |
46 | if (res_ninit(res_state) != 0) { |
47 | SPF_error("Failed to call res_ninit()"); |
47 | SPF_error("Failed to call res_ninit()"); |
48 | } |
48 | } |
49 | @@ -152,20 +157,45 @@ |
49 | @@ -152,20 +157,45 @@ |
50 | else { |
50 | else { |
51 | res_state = (struct __res_state *)res_spec; |
51 | res_state = (struct __res_state *)res_spec; |
52 | } |
52 | } |
53 | +#endif |
53 | +#endif |
54 | + |
54 | + |
55 | + responselen = 2048; |
55 | + responselen = 2048; |
56 | + responsebuf = (u_char *)malloc(responselen); |
56 | + responsebuf = (u_char *)malloc(responselen); |
57 | + memset(responsebuf, 0, responselen); |
57 | + memset(responsebuf, 0, responselen); |
58 | + |
58 | + |
59 | + /* |
59 | + /* |
60 | + * Retry the lookup until our response buffer is big enough. |
60 | + * Retry the lookup until our response buffer is big enough. |
61 | + * |
61 | + * |
62 | + * This loop repeats until either we fail a lookup or we succeed. |
62 | + * This loop repeats until either we fail a lookup or we succeed. |
63 | + * The size of the response buffer is monotonic increasing, so eventually we |
63 | + * The size of the response buffer is monotonic increasing, so eventually we |
64 | + * must either succeed, or we try to malloc more RAM than we can. |
64 | + * must either succeed, or we try to malloc more RAM than we can. |
65 | + * |
65 | + * |
66 | + * The Linux man pages do not describe res_nquery adequately. Solaris says: |
66 | + * The Linux man pages do not describe res_nquery adequately. Solaris says: |
67 | + * |
67 | + * |
68 | + * The res_nquery() and res_query() routines return a length that may be bigger |
68 | + * The res_nquery() and res_query() routines return a length that may be bigger |
69 | + * than anslen. In that case, retry the query with a larger buf. The answer to the |
69 | + * than anslen. In that case, retry the query with a larger buf. The answer to the |
70 | + * second query may be larger still], so it is recommended that you supply a buf |
70 | + * second query may be larger still], so it is recommended that you supply a buf |
71 | + * larger than the answer returned by the previous query. answer must be large |
71 | + * larger than the answer returned by the previous query. answer must be large |
72 | + * enough to receive a maximum UDP response from the server or parts of the answer |
72 | + * enough to receive a maximum UDP response from the server or parts of the answer |
73 | + * will be silently discarded. The default maximum UDP response size is 512 bytes. |
73 | + * will be silently discarded. The default maximum UDP response size is 512 bytes. |
74 | + */ |
74 | + */ |
75 | + for (;;) { |
75 | + for (;;) { |
76 | 76 | ||
77 | /* |
77 | /* |
78 | * try resolving the name |
78 | * try resolving the name |
79 | */ |
79 | */ |
80 | #if HAVE_DECL_RES_NINIT |
80 | #if HAVE_DECL_RES_NINIT |
81 | dns_len = res_nquery(res_state, domain, ns_c_in, rr_type, |
81 | dns_len = res_nquery(res_state, domain, ns_c_in, rr_type, |
82 | - response, sizeof(response)); |
82 | - response, sizeof(response)); |
83 | + responsebuf, responselen); |
83 | + responsebuf, responselen); |
84 | #else |
84 | #else |
85 | dns_len = res_query(domain, ns_c_in, rr_type, |
85 | dns_len = res_query(domain, ns_c_in, rr_type, |
86 | - response, sizeof(response)); |
86 | - response, sizeof(response)); |
87 | + responsebuf, responselen); |
87 | + responsebuf, responselen); |
88 | #endif |
88 | #endif |
89 | 89 | ||
90 | if ( dns_len < 0 ) { |
90 | if ( dns_len < 0 ) { |
91 | + /* We failed to perform a lookup. */ |
91 | + /* We failed to perform a lookup. */ |
92 | /* This block returns unconditionally. */ |
92 | /* This block returns unconditionally. */ |
93 | + free(responsebuf); |
93 | + free(responsebuf); |
94 | if ( spf_dns_server->debug ) |
94 | if ( spf_dns_server->debug ) |
95 | SPF_debugf( "query failed: err = %d %s (%d): %s", |
95 | SPF_debugf( "query failed: err = %d %s (%d): %s", |
96 | dns_len, hstrerror( SPF_h_errno ), SPF_h_errno, |
96 | dns_len, hstrerror( SPF_h_errno ), SPF_h_errno, |
97 | @@ -178,6 +208,25 @@ |
97 | @@ -178,6 +208,25 @@ |
98 | return SPF_dns_rr_new_init(spf_dns_server, |
98 | return SPF_dns_rr_new_init(spf_dns_server, |
99 | domain, rr_type, 0, SPF_h_errno); |
99 | domain, rr_type, 0, SPF_h_errno); |
100 | } |
100 | } |
101 | + else if (dns_len > responselen) { |
101 | + else if (dns_len > responselen) { |
102 | + /* We managed a lookup but our buffer was too small. */ |
102 | + /* We managed a lookup but our buffer was too small. */ |
103 | + responselen = dns_len + (dns_len >> 1); |
103 | + responselen = dns_len + (dns_len >> 1); |
104 | +#if 0 |
104 | +#if 0 |
105 | + /* Sanity-trap - we should never hit this. */ |
105 | + /* Sanity-trap - we should never hit this. */ |
106 | + if (responselen > 1048576) { /* One megabyte. */ |
106 | + if (responselen > 1048576) { /* One megabyte. */ |
107 | + free(responsebuf); |
107 | + free(responsebuf); |
108 | + return SPF_dns_rr_new_init(spf_dns_server, |
108 | + return SPF_dns_rr_new_init(spf_dns_server, |
109 | + domain, rr_type, 0, SPF_h_errno); |
109 | + domain, rr_type, 0, SPF_h_errno); |
110 | + } |
110 | + } |
111 | +#endif |
111 | +#endif |
112 | + responsebuf = realloc(responsebuf, responselen); |
112 | + responsebuf = realloc(responsebuf, responselen); |
113 | + } |
113 | + } |
114 | + else { |
114 | + else { |
115 | + /* We managed a lookup, and our buffer was large enough. */ |
115 | + /* We managed a lookup, and our buffer was large enough. */ |
116 | + responselen = dns_len; |
116 | + responselen = dns_len; |
117 | + break; |
117 | + break; |
118 | + } |
118 | + } |
119 | + } |
119 | + } |
120 | 120 | ||
121 | /* |
121 | /* |
122 | * initialize stuff |
122 | * initialize stuff |
123 | @@ -185,12 +234,13 @@ |
123 | @@ -185,12 +234,13 @@ |
124 | spfrr = SPF_dns_rr_new_init(spf_dns_server, |
124 | spfrr = SPF_dns_rr_new_init(spf_dns_server, |
125 | domain, rr_type, 0, NETDB_SUCCESS); |
125 | domain, rr_type, 0, NETDB_SUCCESS); |
126 | 126 | ||
127 | - err = ns_initparse( response, dns_len, &ns_handle ); |
127 | - err = ns_initparse( response, dns_len, &ns_handle ); |
128 | + err = ns_initparse(responsebuf, responselen, &ns_handle); |
128 | + err = ns_initparse(responsebuf, responselen, &ns_handle); |
129 | 129 | ||
130 | if ( err < 0 ) { /* 0 or -1 */ |
130 | if ( err < 0 ) { /* 0 or -1 */ |
131 | if ( spf_dns_server->debug ) |
131 | if ( spf_dns_server->debug ) |
132 | SPF_debugf( "ns_initparse failed: err = %d %s (%d)", |
132 | SPF_debugf( "ns_initparse failed: err = %d %s (%d)", |
133 | err, strerror( errno ), errno ); |
133 | err, strerror( errno ), errno ); |
134 | + free(responsebuf); |
134 | + free(responsebuf); |
135 | return spfrr; |
135 | return spfrr; |
136 | } |
136 | } |
137 | 137 | ||
138 | @@ -226,6 +276,7 @@ |
138 | @@ -226,6 +276,7 @@ |
139 | if ( spf_dns_server->debug > 1 ) |
139 | if ( spf_dns_server->debug > 1 ) |
140 | SPF_debugf( "ns_parserr failed: err = %d %s (%d)", |
140 | SPF_debugf( "ns_parserr failed: err = %d %s (%d)", |
141 | err, strerror( errno ), errno ); |
141 | err, strerror( errno ), errno ); |
142 | + free(responsebuf); |
142 | + free(responsebuf); |
143 | return spfrr; |
143 | return spfrr; |
144 | } |
144 | } |
145 | 145 | ||
146 | @@ -257,8 +308,8 @@ |
146 | @@ -257,8 +308,8 @@ |
147 | break; |
147 | break; |
148 | 148 | ||
149 | case ns_t_ns: |
149 | case ns_t_ns: |
150 | - err = ns_name_uncompress( response, |
150 | - err = ns_name_uncompress( response, |
151 | - response + sizeof( response ), |
151 | - response + sizeof( response ), |
152 | + err = ns_name_uncompress( responsebuf, |
152 | + err = ns_name_uncompress( responsebuf, |
153 | + responsebuf + responselen, |
153 | + responsebuf + responselen, |
154 | rdata, |
154 | rdata, |
155 | name_buf, sizeof( name_buf ) ); |
155 | name_buf, sizeof( name_buf ) ); |
156 | if ( err < 0 ) /* 0 or -1 */ |
156 | if ( err < 0 ) /* 0 or -1 */ |
157 | @@ -271,8 +322,8 @@ |
157 | @@ -271,8 +322,8 @@ |
158 | break; |
158 | break; |
159 | 159 | ||
160 | case ns_t_cname: |
160 | case ns_t_cname: |
161 | - err = ns_name_uncompress( response, |
161 | - err = ns_name_uncompress( response, |
162 | - response + sizeof( response ), |
162 | - response + sizeof( response ), |
163 | + err = ns_name_uncompress( responsebuf, |
163 | + err = ns_name_uncompress( responsebuf, |
164 | + responsebuf + responselen, |
164 | + responsebuf + responselen, |
165 | rdata, |
165 | rdata, |
166 | name_buf, sizeof( name_buf ) ); |
166 | name_buf, sizeof( name_buf ) ); |
167 | if ( err < 0 ) /* 0 or -1 */ |
167 | if ( err < 0 ) /* 0 or -1 */ |
168 | @@ -286,8 +337,8 @@ |
168 | @@ -286,8 +337,8 @@ |
169 | 169 | ||
170 | case ns_t_mx: |
170 | case ns_t_mx: |
171 | prio = ns_get16( rdata ); |
171 | prio = ns_get16( rdata ); |
172 | - err = ns_name_uncompress( response, |
172 | - err = ns_name_uncompress( response, |
173 | - response + sizeof( response ), |
173 | - response + sizeof( response ), |
174 | + err = ns_name_uncompress( responsebuf, |
174 | + err = ns_name_uncompress( responsebuf, |
175 | + responsebuf + sizeof( responselen ), |
175 | + responsebuf + sizeof( responselen ), |
176 | rdata + NS_INT16SZ, |
176 | rdata + NS_INT16SZ, |
177 | name_buf, sizeof( name_buf ) ); |
177 | name_buf, sizeof( name_buf ) ); |
178 | if ( err < 0 ) /* 0 or -1 */ |
178 | if ( err < 0 ) /* 0 or -1 */ |
179 | @@ -300,14 +351,13 @@ |
179 | @@ -300,14 +351,13 @@ |
180 | break; |
180 | break; |
181 | 181 | ||
182 | case ns_t_txt: |
182 | case ns_t_txt: |
183 | - rdata_end = rdata + rdlen; |
183 | - rdata_end = rdata + rdlen; |
184 | SPF_debugf( "TXT: (%d) \"%.*s\"", |
184 | SPF_debugf( "TXT: (%d) \"%.*s\"", |
185 | rdlen, rdlen-1, rdata+1 ); |
185 | rdlen, rdlen-1, rdata+1 ); |
186 | break; |
186 | break; |
187 | 187 | ||
188 | case ns_t_ptr: |
188 | case ns_t_ptr: |
189 | - err = ns_name_uncompress( response, |
189 | - err = ns_name_uncompress( response, |
190 | - response + sizeof( response ), |
190 | - response + sizeof( response ), |
191 | + err = ns_name_uncompress( responsebuf, |
191 | + err = ns_name_uncompress( responsebuf, |
192 | + responsebuf + responselen, |
192 | + responsebuf + responselen, |
193 | rdata, |
193 | rdata, |
194 | name_buf, sizeof( name_buf ) ); |
194 | name_buf, sizeof( name_buf ) ); |
195 | if ( err < 0 ) /* 0 or -1 */ |
195 | if ( err < 0 ) /* 0 or -1 */ |
196 | @@ -341,18 +391,21 @@ |
196 | @@ -341,18 +391,21 @@ |
197 | { |
197 | { |
198 | case ns_t_a: |
198 | case ns_t_a: |
199 | if ( SPF_dns_rr_buf_realloc( spfrr, cnt, |
199 | if ( SPF_dns_rr_buf_realloc( spfrr, cnt, |
200 | - sizeof( spfrr->rr[cnt]->a ) ) != SPF_E_SUCCESS ) |
200 | - sizeof( spfrr->rr[cnt]->a ) ) != SPF_E_SUCCESS ) |
201 | + sizeof(spfrr->rr[cnt]->a)) != SPF_E_SUCCESS) { |
201 | + sizeof(spfrr->rr[cnt]->a)) != SPF_E_SUCCESS) { |
202 | + free(responsebuf); |
202 | + free(responsebuf); |
203 | return spfrr; |
203 | return spfrr; |
204 | - memmove( &spfrr->rr[cnt]->a, rdata, sizeof( spfrr->rr[cnt]->a ) ); |
204 | - memmove( &spfrr->rr[cnt]->a, rdata, sizeof( spfrr->rr[cnt]->a ) ); |
205 | + } |
205 | + } |
206 | + memcpy(&spfrr->rr[cnt]->a, rdata, sizeof(spfrr->rr[cnt]->a)); |
206 | + memcpy(&spfrr->rr[cnt]->a, rdata, sizeof(spfrr->rr[cnt]->a)); |
207 | cnt++; |
207 | cnt++; |
208 | break; |
208 | break; |
209 | 209 | ||
210 | case ns_t_aaaa: |
210 | case ns_t_aaaa: |
211 | if ( SPF_dns_rr_buf_realloc( spfrr, cnt, |
211 | if ( SPF_dns_rr_buf_realloc( spfrr, cnt, |
212 | - sizeof( spfrr->rr[cnt]->aaaa ) ) != SPF_E_SUCCESS ) |
212 | - sizeof( spfrr->rr[cnt]->aaaa ) ) != SPF_E_SUCCESS ) |
213 | + sizeof(spfrr->rr[cnt]->aaaa)) != SPF_E_SUCCESS) { |
213 | + sizeof(spfrr->rr[cnt]->aaaa)) != SPF_E_SUCCESS) { |
214 | + free(responsebuf); |
214 | + free(responsebuf); |
215 | return spfrr; |
215 | return spfrr; |
216 | - memmove( &spfrr->rr[cnt]->aaaa, rdata, sizeof( spfrr->rr[cnt]->aaaa ) ); |
216 | - memmove( &spfrr->rr[cnt]->aaaa, rdata, sizeof( spfrr->rr[cnt]->aaaa ) ); |
217 | - |
217 | - |
218 | + } |
218 | + } |
219 | + memcpy(&spfrr->rr[cnt]->aaaa, rdata, sizeof(spfrr->rr[cnt]->aaaa)); |
219 | + memcpy(&spfrr->rr[cnt]->aaaa, rdata, sizeof(spfrr->rr[cnt]->aaaa)); |
220 | cnt++; |
220 | cnt++; |
221 | break; |
221 | break; |
222 | 222 | ||
223 | @@ -364,8 +417,8 @@ |
223 | @@ -364,8 +417,8 @@ |
224 | break; |
224 | break; |
225 | 225 | ||
226 | case ns_t_mx: |
226 | case ns_t_mx: |
227 | - err = ns_name_uncompress( response, |
227 | - err = ns_name_uncompress( response, |
228 | - response + sizeof( response ), |
228 | - response + sizeof( response ), |
229 | + err = ns_name_uncompress(responsebuf, |
229 | + err = ns_name_uncompress(responsebuf, |
230 | + responsebuf + responselen, |
230 | + responsebuf + responselen, |
231 | rdata + NS_INT16SZ, |
231 | rdata + NS_INT16SZ, |
232 | name_buf, sizeof( name_buf ) ); |
232 | name_buf, sizeof( name_buf ) ); |
233 | if ( err < 0 ) /* 0 or -1 */ |
233 | if ( err < 0 ) /* 0 or -1 */ |
234 | @@ -373,12 +426,15 @@ |
234 | @@ -373,12 +426,15 @@ |
235 | if ( spf_dns_server->debug > 1 ) |
235 | if ( spf_dns_server->debug > 1 ) |
236 | SPF_debugf( "ns_name_uncompress failed: err = %d %s (%d)", |
236 | SPF_debugf( "ns_name_uncompress failed: err = %d %s (%d)", |
237 | err, strerror( errno ), errno ); |
237 | err, strerror( errno ), errno ); |
238 | + free(responsebuf); |
238 | + free(responsebuf); |
239 | return spfrr; |
239 | return spfrr; |
240 | } |
240 | } |
241 | 241 | ||
242 | if ( SPF_dns_rr_buf_realloc( spfrr, cnt, |
242 | if ( SPF_dns_rr_buf_realloc( spfrr, cnt, |
243 | - strlen( name_buf ) + 1 ) != SPF_E_SUCCESS ) |
243 | - strlen( name_buf ) + 1 ) != SPF_E_SUCCESS ) |
244 | + strlen(name_buf) + 1 ) != SPF_E_SUCCESS) { |
244 | + strlen(name_buf) + 1 ) != SPF_E_SUCCESS) { |
245 | + free(responsebuf); |
245 | + free(responsebuf); |
246 | return spfrr; |
246 | return spfrr; |
247 | + } |
247 | + } |
248 | strcpy( spfrr->rr[cnt]->mx, name_buf ); |
248 | strcpy( spfrr->rr[cnt]->mx, name_buf ); |
249 | 249 | ||
250 | cnt++; |
250 | cnt++; |
251 | @@ -390,8 +446,12 @@ |
251 | @@ -390,8 +446,12 @@ |
252 | u_char *src, *dst; |
252 | u_char *src, *dst; |
253 | size_t len; |
253 | size_t len; |
254 | 254 | ||
255 | - if ( SPF_dns_rr_buf_realloc( spfrr, cnt, rdlen ) != SPF_E_SUCCESS ) |
255 | - if ( SPF_dns_rr_buf_realloc( spfrr, cnt, rdlen ) != SPF_E_SUCCESS ) |
256 | + /* Just rdlen is enough because there is at least one |
256 | + /* Just rdlen is enough because there is at least one |
257 | + * length byte. */ |
257 | + * length byte. */ |
258 | + if (SPF_dns_rr_buf_realloc(spfrr, cnt, rdlen) != SPF_E_SUCCESS) { |
258 | + if (SPF_dns_rr_buf_realloc(spfrr, cnt, rdlen) != SPF_E_SUCCESS) { |
259 | + free(responsebuf); |
259 | + free(responsebuf); |
260 | return spfrr; |
260 | return spfrr; |
261 | + } |
261 | + } |
262 | 262 | ||
263 | dst = (u_char *)(spfrr->rr[cnt]->txt); |
263 | dst = (u_char *)(spfrr->rr[cnt]->txt); |
264 | len = 0; |
264 | len = 0; |
265 | @@ -400,15 +460,22 @@ |
265 | @@ -400,15 +460,22 @@ |
266 | { |
266 | { |
267 | len = *src; |
267 | len = *src; |
268 | src++; |
268 | src++; |
269 | + rdlen--; |
269 | + rdlen--; |
270 | + |
270 | + |
271 | + /* Avoid buffer overrun if len is junk. */ |
271 | + /* Avoid buffer overrun if len is junk. */ |
272 | + if (len > rdlen) |
272 | + if (len > rdlen) |
273 | + len = rdlen; |
273 | + len = rdlen; |
274 | memcpy( dst, src, len ); |
274 | memcpy( dst, src, len ); |
275 | dst += len; |
275 | dst += len; |
276 | src += len; |
276 | src += len; |
277 | - rdlen -= len + 1; |
277 | - rdlen -= len + 1; |
278 | + rdlen -= len; |
278 | + rdlen -= len; |
279 | } |
279 | } |
280 | *dst = '\0'; |
280 | *dst = '\0'; |
281 | } else { |
281 | } else { |
282 | - if ( SPF_dns_rr_buf_realloc( spfrr, cnt, 1 ) != SPF_E_SUCCESS ) |
282 | - if ( SPF_dns_rr_buf_realloc( spfrr, cnt, 1 ) != SPF_E_SUCCESS ) |
283 | + if (SPF_dns_rr_buf_realloc(spfrr, cnt, 1) != SPF_E_SUCCESS) { |
283 | + if (SPF_dns_rr_buf_realloc(spfrr, cnt, 1) != SPF_E_SUCCESS) { |
284 | + free(responsebuf); |
284 | + free(responsebuf); |
285 | return spfrr; |
285 | return spfrr; |
286 | + } |
286 | + } |
287 | spfrr->rr[cnt]->txt[0] = '\0'; |
287 | spfrr->rr[cnt]->txt[0] = '\0'; |
288 | } |
288 | } |
289 | 289 | ||
290 | @@ -416,8 +483,8 @@ |
290 | @@ -416,8 +483,8 @@ |
291 | break; |
291 | break; |
292 | 292 | ||
293 | case ns_t_ptr: |
293 | case ns_t_ptr: |
294 | - err = ns_name_uncompress( response, |
294 | - err = ns_name_uncompress( response, |
295 | - response + sizeof( response ), |
295 | - response + sizeof( response ), |
296 | + err = ns_name_uncompress(responsebuf, |
296 | + err = ns_name_uncompress(responsebuf, |
297 | + responsebuf + responselen, |
297 | + responsebuf + responselen, |
298 | rdata, |
298 | rdata, |
299 | name_buf, sizeof( name_buf ) ); |
299 | name_buf, sizeof( name_buf ) ); |
300 | if ( err < 0 ) /* 0 or -1 */ |
300 | if ( err < 0 ) /* 0 or -1 */ |
301 | @@ -425,12 +492,15 @@ |
301 | @@ -425,12 +492,15 @@ |
302 | if ( spf_dns_server->debug > 1 ) |
302 | if ( spf_dns_server->debug > 1 ) |
303 | SPF_debugf( "ns_name_uncompress failed: err = %d %s (%d)", |
303 | SPF_debugf( "ns_name_uncompress failed: err = %d %s (%d)", |
304 | err, strerror( errno ), errno ); |
304 | err, strerror( errno ), errno ); |
305 | + free(responsebuf); |
305 | + free(responsebuf); |
306 | return spfrr; |
306 | return spfrr; |
307 | } |
307 | } |
308 | 308 | ||
309 | if ( SPF_dns_rr_buf_realloc( spfrr, cnt, |
309 | if ( SPF_dns_rr_buf_realloc( spfrr, cnt, |
310 | - strlen( name_buf ) + 1 ) != SPF_E_SUCCESS ) |
310 | - strlen( name_buf ) + 1 ) != SPF_E_SUCCESS ) |
311 | + strlen(name_buf) + 1) != SPF_E_SUCCESS) { |
311 | + strlen(name_buf) + 1) != SPF_E_SUCCESS) { |
312 | + free(responsebuf); |
312 | + free(responsebuf); |
313 | return spfrr; |
313 | return spfrr; |
314 | + } |
314 | + } |
315 | strcpy( spfrr->rr[cnt]->ptr, name_buf ); |
315 | strcpy( spfrr->rr[cnt]->ptr, name_buf ); |
316 | 316 | ||
317 | cnt++; |
317 | cnt++; |
318 | @@ -447,6 +517,7 @@ |
318 | @@ -447,6 +517,7 @@ |
319 | if ( spfrr->num_rr == 0 ) |
319 | if ( spfrr->num_rr == 0 ) |
320 | spfrr->herrno = NO_DATA; |
320 | spfrr->herrno = NO_DATA; |
321 | 321 | ||
322 | + free(responsebuf); |
322 | + free(responsebuf); |
323 | return spfrr; |
323 | return spfrr; |
324 | } |
324 | } |
325 | 325 |