Added leashdll/wshelper related files from KFW
[krb5.git] / src / windows / wshelper / res_comp.c
1 /*
2  *
3  *      @doc RESOLVE
4  *
5  * @module res_comp.c |
6  *
7  *        Contains the implementations for dn_comp and rdn_expand as well as
8  *        some other functions used internally by these two functions.
9  *
10  *        WSHelper DNS/Hesiod Library for WINSOCK
11  *
12  */
13
14 /*
15  * Copyright (c) 1985 Regents of the University of California.
16  * All rights reserved.
17  *
18  * Redistribution and use in source and binary forms, with or without
19  * modification, are permitted provided that the following conditions
20  * are met:
21  * 1. Redistributions of source code must retain the above copyright
22  *    notice, this list of conditions and the following disclaimer.
23  * 2. Redistributions in binary form must reproduce the above copyright
24  *    notice, this list of conditions and the following disclaimer in the
25  *    documentation and/or other materials provided with the distribution.
26  * 3. All advertising materials mentioning features or use of this software
27  *    must display the following acknowledgement:
28  *      This product includes software developed by the University of
29  *      California, Berkeley and its contributors.
30  * 4. Neither the name of the University nor the names of its contributors
31  *    may be used to endorse or promote products derived from this software
32  *    without specific prior written permission.
33  *
34  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
35  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44  * SUCH DAMAGE.
45  */
46
47 #if defined(LIBC_SCCS) && !defined(lint)
48 static char sccsid[] = "@(#)res_comp.c  6.22 (Berkeley) 3/19/91";
49 #endif /* LIBC_SCCS and not lint */
50
51 #include <windows.h>
52 #include <winsock.h>
53 #include <resolv.h>
54 #include <stdio.h>
55
56
57 static dn_find();
58
59 /*
60         replacement for dn_expand called rdn_expand. Older versions of
61         the DLL used to this as dn_expand but this has caused some
62         conflict with more recent versions of the MSDEV
63         libraries. rdn_expand() expands the compressed domain name comp_dn to
64         a full domain name.  Expanded names are converted to upper case.
65
66         \param[in]      msg             msg is a pointer to the  beginning  of  the  message
67         \param[in]      eomorig
68         \param[in]                      comp_dn the compressed domain name.
69         \param[in, out]         expn_dn a pointer to the result buffer
70         \param[in]                      length  size of the result in expn_dn
71
72         \retval                         the size of compressed name is returned or -1 if there was an error.
73 */
74
75
76
77 int WINAPI
78 rdn_expand(const u_char *msg, const u_char *eomorig,
79                    const u_char *comp_dn, u_char *exp_dn, int length)
80 {
81     register u_char *cp, *dn;
82     register int n, c;
83     u_char *eom;
84         INT_PTR len = -1;
85     int checked = 0;
86
87     dn = exp_dn;
88     cp = (u_char *)comp_dn;
89     eom = exp_dn + length;
90     /*
91      * fetch next label in domain name
92      */
93     while (n = *cp++) {
94         /*
95          * Check for indirection
96          */
97         switch (n & INDIR_MASK) {
98         case 0:
99             if (dn != exp_dn) {
100                 if (dn >= eom)
101                     return (-1);
102                 *dn++ = '.';
103             }
104             if (dn+n >= eom)
105                 return (-1);
106             checked += n + 1;
107             while (--n >= 0) {
108                 if ((c = *cp++) == '.') {
109                     if (dn + n + 2 >= eom)
110                         return (-1);
111                     *dn++ = '\\';
112                 }
113                 *dn++ = c;
114                 if (cp >= eomorig)      /* out of range */
115                     return(-1);
116             }
117             break;
118
119         case INDIR_MASK:
120             if (len < 0)
121                 len = cp - comp_dn + 1;
122             cp = (u_char *)msg + (((n & 0x3f) << 8) | (*cp & 0xff));
123             if (cp < msg || cp >= eomorig)  /* out of range */
124                 return(-1);
125             checked += 2;
126             /*
127              * Check for loops in the compressed name;
128              * if we've looked at the whole message,
129              * there must be a loop.
130              */
131             if (checked >= eomorig - msg)
132                 return (-1);
133             break;
134
135         default:
136             return (-1);                    /* flag error */
137         }
138     }
139     *dn = '\0';
140     if (len < 0)
141         len = cp - comp_dn;
142     return (int)(len);
143 }
144
145
146 /*
147         Compress domain name 'exp_dn' into 'comp_dn'
148         \param[in]      exp_dn  name to compress
149         \param[in, out] comp_dn         result of the compression
150         \paramp[in]     length                  the size of the array pointed to by 'comp_dn'.
151         \param[in, out] dnptrs          a list of pointers to previous compressed names. dnptrs[0]
152                                                                 is a pointer to the beginning of the message. The list ends with NULL.
153         \param[in]      lastdnptr               a pointer to the end of the arrary pointed to by 'dnptrs'. Side effect
154                                                                 is to update the list of pointers for labels inserted into the
155                                                                 message as we compress the name. If 'dnptr' is NULL, we don't try to
156                                                                 compress names. If 'lastdnptr' is NULL, we don't update the list.
157         \retval                                         Return the size of the compressed name or -1
158  */
159 int WINAPI
160 dn_comp(const u_char *exp_dn, u_char *comp_dn, int length,
161         u_char **dnptrs, u_char **lastdnptr)
162 {
163     register u_char *cp, *dn;
164     register int c, l;
165     u_char **cpp, **lpp, *sp, *eob;
166     u_char *msg;
167
168     dn = (u_char *)exp_dn;
169     cp = comp_dn;
170     eob = cp + length;
171     if (dnptrs != NULL) {
172         if ((msg = *dnptrs++) != NULL) {
173             for (cpp = dnptrs; *cpp != NULL; cpp++)
174                 ;
175             lpp = cpp;      /* end of list to search */
176         }
177     } else
178         msg = NULL;
179     for (c = *dn++; c != '\0'; ) {
180         /* look to see if we can use pointers */
181         if (msg != NULL) {
182             if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
183                 if (cp+1 >= eob)
184                     return (-1);
185                 *cp++ = (l >> 8) | INDIR_MASK;
186                 *cp++ = l % 256;
187                 return (int)(cp - comp_dn);
188             }
189             /* not found, save it */
190             if (lastdnptr != NULL && cpp < lastdnptr-1) {
191                 *cpp++ = cp;
192                 *cpp = NULL;
193             }
194         }
195         sp = cp++;      /* save ptr to length byte */
196         do {
197             if (c == '.') {
198                 c = *dn++;
199                 break;
200             }
201             if (c == '\\') {
202                 if ((c = *dn++) == '\0')
203                     break;
204             }
205             if (cp >= eob) {
206                 if (msg != NULL)
207                     *lpp = NULL;
208                 return (-1);
209             }
210             *cp++ = c;
211         } while ((c = *dn++) != '\0');
212         /* catch trailing '.'s but not '..' */
213         if ((l =(int)( cp - sp - 1)) == 0 && c == '\0') {
214             cp--;
215             break;
216         }
217         if (l <= 0 || l > MAXLABEL) {
218             if (msg != NULL)
219                 *lpp = NULL;
220             return (-1);
221         }
222         *sp = l;
223     }
224     if (cp >= eob) {
225         if (msg != NULL)
226             *lpp = NULL;
227         return (-1);
228     }
229     *cp++ = '\0';
230     return (int)(cp - comp_dn);
231 }
232
233 /*
234  * Skip over a compressed domain name. Return the size or -1.
235  */
236 __dn_skipname(const u_char *comp_dn, const u_char *eom)
237 {
238     register u_char *cp;
239     register int n;
240
241     cp = (u_char *)comp_dn;
242     while (cp < eom && (n = *cp++)) {
243         /*
244          * check for indirection
245          */
246         switch (n & INDIR_MASK) {
247         case 0:         /* normal case, n == len */
248             cp += n;
249             continue;
250         default:        /* illegal type */
251             return (-1);
252         case INDIR_MASK:        /* indirection */
253             cp++;
254         }
255         break;
256     }
257     return (int)(cp - comp_dn);
258 }
259
260 /*
261  * Search for expanded name from a list of previously compressed names.
262  * Return the offset from msg if found or -1.
263  * dnptrs is the pointer to the first name on the list,
264  * not the pointer to the start of the message.
265  */
266 static
267 dn_find(u_char *exp_dn, u_char *msg, u_char **dnptrs, u_char **lastdnptr)
268 {
269     register u_char *dn, *cp, **cpp;
270     register int n;
271     u_char *sp;
272
273     for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
274         dn = exp_dn;
275         sp = cp = *cpp;
276         while (n = *cp++) {
277             /*
278              * check for indirection
279              */
280             switch (n & INDIR_MASK) {
281             case 0:         /* normal case, n == len */
282                 while (--n >= 0) {
283                     if (*dn == '.')
284                         goto next;
285                     if (*dn == '\\')
286                         dn++;
287                     if (*dn++ != *cp++)
288                         goto next;
289                 }
290                 if ((n = *dn++) == '\0' && *cp == '\0')
291                     return (int)(sp - msg);
292                 if (n == '.')
293                     continue;
294                 goto next;
295
296             default:        /* illegal type */
297                 return (-1);
298
299             case INDIR_MASK:        /* indirection */
300                 cp = msg + (((n & 0x3f) << 8) | *cp);
301             }
302         }
303         if (*dn == '\0')
304             return (int)(sp - msg);
305     next:   ;
306     }
307     return (-1);
308 }
309
310 /*
311  * Routines to insert/extract short/long's. Must account for byte
312  * order and non-alignment problems. This code at least has the
313  * advantage of being portable.
314  *
315  * used by sendmail.
316  */
317
318 u_short
319 _getshort(u_char *msgp)
320 {
321     register u_char *p = (u_char *) msgp;
322 #ifdef vax
323     /*
324      * vax compiler doesn't put shorts in registers
325      */
326     register u_long u;
327 #else
328     register u_short u;
329 #endif
330
331     u = *p++ << 8;
332     return ((u_short)(u | *p));
333 }
334
335 u_long
336 _getlong(u_char *msgp)
337 {
338     register u_char *p = (u_char *) msgp;
339     register u_long u;
340
341     u = *p++; u <<= 8;
342     u |= *p++; u <<= 8;
343     u |= *p++; u <<= 8;
344     return (u | *p);
345 }
346
347 void
348 #ifdef __STDC__
349 __putshort(register u_short s, register u_char *msgp)
350 #else
351 __putshort(s, msgp)
352     register u_short s;
353     register u_char *msgp;
354 #endif
355 {
356     msgp[1] = LOBYTE(s);
357     msgp[0] = HIBYTE(s);
358 }
359
360 void
361 __putlong(l, msgp)
362     register u_long l;
363     register u_char *msgp;
364 {
365     msgp[3] = LOBYTE(LOWORD(l));
366     msgp[2] = HIBYTE(LOWORD(l));
367     msgp[1] = LOBYTE(HIWORD(l));
368     msgp[0] = HIBYTE(HIWORD(l));
369 }