1 /* dns stringing functions */
2 #include <errno.h>
3 #include "ldapdns.h"
4 #include "mem.h"
5
name_to_dns_fix(str_t retbuf,char * name,int splithow)6 void name_to_dns_fix(str_t retbuf, char *name, int splithow)
7 {
8 register int ch;
9
10 ch = (splithow ? '|' : '.');
11 if (splithow == 2) ch = '@';
12
13 /* safe if name is truly ASCIIZ */
14 while (*name == ch)
15 ++name;
16
17 str_init(retbuf);
18 while (*name) {
19 register char *start = name;
20 register unsigned length;
21 register int tmp;
22
23 while (*name && *name != ch)
24 ++name;
25 length = name - start;
26 if (length >= 127 && !splithow) {
27 warning("name-segment too long: %s", name);
28 return; /* invalid */
29 }
30
31 while (length) {
32 /* tmp is a function of length, and length must be >0 */
33 str_addch(retbuf, tmp = length > 127 ? 127 : length);
34 str_catb(retbuf, start, tmp);
35 length -= tmp;
36 start += tmp;
37 }
38 while (*name == ch)
39 ++name;
40 if (splithow == 2) {
41 splithow = 0;
42 ch = '.';
43 }
44 }
45 }
46
dns_to_name(str_t retbuf,char * dns,int joinhow)47 void dns_to_name(str_t retbuf, char *dns, int joinhow)
48 {
49 const char *ch = ".|@";
50
51 str_init(retbuf);
52 while (*dns) {
53 str_catb(retbuf, dns+1, dns[0]);
54 str_addch(retbuf, ch[joinhow]);
55 if (joinhow == 2) joinhow = 0;
56 dns += (dns[0]+1);
57 }
58 /* will have two dots... */
59 str_chop(retbuf);
60 }
61
62 /* these lists are built BACKWARDS so that we can just pop() off the first
63 * entries easily when searching for wildcards
64 */
join_name_parts(str_t retbuf,list_t p)65 void join_name_parts(str_t retbuf, list_t p)
66 {
67 str_init(retbuf);
68 while (p) {
69 str_cat(retbuf, p->str);
70 str_addch(retbuf, '.');
71 p = p->next;
72 }
73 str_chop(retbuf);
74 }
join_dns_parts(str_t retbuf,list_t p)75 void join_dns_parts(str_t retbuf, list_t p)
76 {
77 str_init(retbuf);
78 while (p) {
79 str_addch(retbuf, __str_clen(p->str));
80 str_cat(retbuf, p->str);
81
82 p = p->next;
83 }
84 str_chop(retbuf);
85 }
split_name_parts(char * name)86 list_t split_name_parts(char *name)
87 {
88 /* name is modified by this routine! */
89 list_t p = 0;
90 register char *start = name;
91
92 while (*start == '.') start++;
93 while (*start) {
94 while (*start && *start != '.') start++;
95 if (*start) {
96 *start = 0;
97 start++;
98 while (*start == '.') start++;
99 }
100
101 list_push(&p, name);
102 name = start;
103 }
104
105 /* list is in reverse */
106 list_reverse(&p);
107
108 return p;
109 }
split_dns_parts(char * name)110 list_t split_dns_parts(char *name)
111 {
112 /* name is modified by this routine! */
113 list_t p = 0;
114 register unsigned int length, nl;
115
116 while (*name) {
117 length = *name;
118 if (length == 0)
119 break;
120 nl = name[length+1];
121 name[length+1] = 0;
122 list_push(&p, name+1);
123 name += length;
124 }
125
126 /* list is in reverse */
127 list_reverse(&p);
128
129 return p;
130 }
131
132 /* packet related */
dns_packet_copy(dns_ctx * c,char * out,unsigned int outlen)133 unsigned int dns_packet_copy(dns_ctx *c, char *out,unsigned int outlen)
134 {
135 while (outlen) {
136 if (c->request_pos >= c->request_len) {
137 errno = EBADMSG;
138 return 0;
139 }
140 *out = c->request_buf[c->request_pos++];
141 ++out; --outlen;
142 }
143 return c->request_pos;
144 }
145
dns_packet_skipname(dns_ctx * c)146 unsigned int dns_packet_skipname(dns_ctx *c)
147 {
148 unsigned char ch;
149
150 for (;;) { /* should be safe because it is bounded and breaks on non-movement */
151 if (c->request_pos >= c->request_len)
152 break;
153 ch = c->request_buf[c->request_pos++];
154 if (ch >= 192) { c->request_pos++; return c->request_pos; }
155 if (ch >= 64) break;
156 if (!ch) return c->request_pos;
157 c->request_pos += ch;
158 }
159
160 errno = EBADMSG;
161 return 0;
162 }
163
dns_packet_getname(dns_ctx * c,char ** d)164 unsigned int dns_packet_getname(dns_ctx *c, char **d)
165 {
166 unsigned int loop = 0;
167 unsigned int state = 0;
168 unsigned int firstcompress = 0;
169 unsigned int where;
170 unsigned char ch;
171 char name[255];
172 unsigned int namelen = 0;
173
174 for (;;) { /* should be safe: breaks on non-movement;
175 OR after 1000 iterations */
176 if (c->request_pos >= c->request_len) goto PROTO;
177 ch = c->request_buf[c->request_pos++];
178 if (++loop >= 1000) goto PROTO;
179
180 if (state) {
181 if (namelen + 1 > sizeof name) goto PROTO;
182 name[namelen++] = ch;
183 --state;
184 } else {
185 while (ch >= 192) {
186 where = ch; where -= 192; where <<= 8;
187 if (c->request_pos >= c->request_len)
188 goto PROTO;
189 ch = c->request_buf[c->request_pos++];
190 if (!firstcompress)
191 firstcompress = c->request_pos;
192 c->request_pos = where + ch;
193 if (c->request_pos >= c->request_len)
194 goto PROTO;
195 ch = c->request_buf[c->request_pos++];
196 if (++loop >= 1000) goto PROTO;
197 }
198 if (ch >= 64) goto PROTO;
199 if (namelen + 1 > sizeof name) goto PROTO;
200 name[namelen++] = ch;
201 if (!ch) break;
202 state = ch;
203 }
204 }
205
206 if (!dns_domain_copy(d,name)) return 0;
207
208 if (firstcompress) c->request_pos = firstcompress;
209 return c->request_pos;
210
211 PROTO:
212 errno = EBADMSG;
213 return 0;
214 }
dns_domain_length(const char * dn)215 unsigned int dns_domain_length(const char *dn)
216 {
217 const char *x;
218 unsigned char c;
219
220 x = dn;
221 while ((c = *x++)) /* should be safe if dn is a valid dns-encoded */
222 x += (unsigned int) c;
223 return x - dn;
224 }
dns_domain_lower(char * dn)225 void dns_domain_lower(char *dn)
226 {
227 char *x;
228 int i;
229
230 x = dn;
231 while (*x) { /* should be safe if dn is a valid dns-encoded */
232 for (i = 1; i <= *x; i++) {
233 /* Clib */
234 dn[i] = tolower(dn[i]);
235 }
236 dn += *x;
237 dn++;
238 x = dn;
239 }
240 }
dns_domain_copy(char ** out,char * in)241 int dns_domain_copy(char **out, char *in)
242 {
243 bin_t retval;
244 unsigned int len;
245
246 len = dns_domain_length(in);
247 bin_init(retval);
248 bin_copy(retval, in, len);
249 if (*out) mem_free(*out);
250 *out = caddr(retval);
251
252 return 1;
253 }
254
255