other-licenses/android/ns_print.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /*	$NetBSD: ns_print.c,v 1.5 2004/11/07 02:19:49 christos Exp $	*/
     3 /*
     4  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
     5  * Copyright (c) 1996-1999 by Internet Software Consortium.
     6  *
     7  * Permission to use, copy, modify, and distribute this software for any
     8  * purpose with or without fee is hereby granted, provided that the above
     9  * copyright notice and this permission notice appear in all copies.
    10  *
    11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
    12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
    13  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
    14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
    16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
    17  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    18  */
    20 /*
    21  * This version of this file is derived from Android 2.3 "Gingerbread",
    22  * which contains uncredited changes by Android/Google developers.  It has
    23  * been modified in 2011 for use in the Android build of Mozilla Firefox by
    24  * Mozilla contributors (including Michael Edwards <m.k.edwards@gmail.com>,
    25  * and Steve Workman <sjhworkman@gmail.com>).
    26  * These changes are offered under the same license as the original NetBSD
    27  * file, whose copyright and license are unchanged above.
    28  */
    30 #define ANDROID_CHANGES 1
    31 #define MOZILLA_NECKO_EXCLUDE_CODE 1 
    33 #include <sys/cdefs.h>
    34 #ifndef lint
    35 #ifdef notdef
    36 static const char rcsid[] = "Id: ns_print.c,v 1.3.2.1.4.5 2004/07/28 20:16:45 marka Exp";
    37 #else
    38 __RCSID("$NetBSD: ns_print.c,v 1.5 2004/11/07 02:19:49 christos Exp $");
    39 #endif
    40 #endif
    42 /* Import. */
    44 #include <sys/types.h>
    45 #include <sys/socket.h>
    47 #include <netinet/in.h>
    48 #include "arpa_nameser.h"
    49 #include <arpa/inet.h>
    51 #include "assertions.h"
    52 #include "dst.h"
    53 #include <errno.h>
    54 #ifdef ANDROID_CHANGES
    55 #include "resolv_private.h"
    56 #else
    57 #include <resolv.h>
    58 #endif
    59 #include <string.h>
    60 #include <ctype.h>
    61 #include <assert.h>
    63 #ifdef SPRINTF_CHAR
    64 # define SPRINTF(x) strlen(sprintf/**/x)
    65 #else
    66 # define SPRINTF(x) ((size_t)sprintf x)
    67 #endif
    69 #ifndef MIN
    70 #define	MIN(x,y)	((x)<(y)?(x):(y))
    71 #endif
    73 /* Forward. */
    75 static size_t	prune_origin(const char *name, const char *origin);
    76 static int	charstr(const u_char *rdata, const u_char *edata,
    77 			char **buf, size_t *buflen);
    78 static int	addname(const u_char *msg, size_t msglen,
    79 			const u_char **p, const char *origin,
    80 			char **buf, size_t *buflen);
    81 static void	addlen(size_t len, char **buf, size_t *buflen);
    82 static int	addstr(const char *src, size_t len,
    83 		       char **buf, size_t *buflen);
    84 static int	addtab(size_t len, size_t target, int spaced,
    85 		       char **buf, size_t *buflen);
    87 /* Macros. */
    89 #define	T(x) \
    90 	do { \
    91 		if ((x) < 0) \
    92 			return (-1); \
    93 	} while (/*CONSTCOND*/0)
    95 /* Public. */
    97 /*
    98  * int
    99  * ns_sprintrr(handle, rr, name_ctx, origin, buf, buflen)
   100  *	Convert an RR to presentation format.
   101  * return:
   102  *	Number of characters written to buf, or -1 (check errno).
   103  */
   104 int
   105 ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
   106 	    const char *name_ctx, const char *origin,
   107 	    char *buf, size_t buflen)
   108 {
   109 	int n;
   111 	n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
   112 			 ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
   113 			 ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
   114 			 name_ctx, origin, buf, buflen);
   115 	return (n);
   116 }
   118 /*
   119  * int
   120  * ns_sprintrrf(msg, msglen, name, class, type, ttl, rdata, rdlen,
   121  *	       name_ctx, origin, buf, buflen)
   122  *	Convert the fields of an RR into presentation format.
   123  * return:
   124  *	Number of characters written to buf, or -1 (check errno).
   125  */
   126 int
   127 ns_sprintrrf(const u_char *msg, size_t msglen,
   128 	    const char *name, ns_class class, ns_type type,
   129 	    u_long ttl, const u_char *rdata, size_t rdlen,
   130 	    const char *name_ctx, const char *origin,
   131 	    char *buf, size_t buflen)
   132 {
   133 	const char *obuf = buf;
   134 	const u_char *edata = rdata + rdlen;
   135 	int spaced = 0;
   137 	const char *comment;
   138 	char tmp[100];
   139 	int len, x;
   141 	/*
   142 	 * Owner.
   143 	 */
   144 	if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
   145 		T(addstr("\t\t\t", (size_t)3, &buf, &buflen));
   146 	} else {
   147 		len = prune_origin(name, origin);
   148 		if (*name == '\0') {
   149 			goto root;
   150 		} else if (len == 0) {
   151 			T(addstr("@\t\t\t", (size_t)4, &buf, &buflen));
   152 		} else {
   153 			T(addstr(name, (size_t)len, &buf, &buflen));
   154 			/* Origin not used or not root, and no trailing dot? */
   155 			if (((origin == NULL || origin[0] == '\0') ||
   156 			    (origin[0] != '.' && origin[1] != '\0' &&
   157 			    name[len] == '\0')) && name[len - 1] != '.') {
   158  root:
   159 				T(addstr(".", (size_t)1, &buf, &buflen));
   160 				len++;
   161 			}
   162 			T(spaced = addtab((size_t)len, 24, spaced, &buf, &buflen));
   163 		}
   164 	}
   166 	/*
   167 	 * TTL, Class, Type.
   168 	 */
   169 	T(x = ns_format_ttl(ttl, buf, buflen));
   170 	addlen((size_t)x, &buf, &buflen);
   171 	len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
   172 	T(addstr(tmp, (size_t)len, &buf, &buflen));
   173 	T(spaced = addtab((size_t)(x + len), (size_t)16, spaced, &buf, &buflen));
   175 	/*
   176 	 * RData.
   177 	 */
   178 	switch (type) {
   179 	case ns_t_a:
   180 		if (rdlen != (size_t)NS_INADDRSZ)
   181 			goto formerr;
   182 		(void) inet_ntop(AF_INET, rdata, buf, buflen);
   183 		addlen(strlen(buf), &buf, &buflen);
   184 		break;
   186 	case ns_t_cname:
   187 	case ns_t_mb:
   188 	case ns_t_mg:
   189 	case ns_t_mr:
   190 	case ns_t_ns:
   191 	case ns_t_ptr:
   192 	case ns_t_dname:
   193 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   194 		break;
   196 	case ns_t_hinfo:
   197 	case ns_t_isdn:
   198 		/* First word. */
   199 		T(len = charstr(rdata, edata, &buf, &buflen));
   200 		if (len == 0)
   201 			goto formerr;
   202 		rdata += len;
   203 		T(addstr(" ", (size_t)1, &buf, &buflen));
   206 		/* Second word, optional in ISDN records. */
   207 		if (type == ns_t_isdn && rdata == edata)
   208 			break;
   210 		T(len = charstr(rdata, edata, &buf, &buflen));
   211 		if (len == 0)
   212 			goto formerr;
   213 		rdata += len;
   214 		break;
   216 	case ns_t_soa: {
   217 		u_long t;
   219 		/* Server name. */
   220 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   221 		T(addstr(" ", (size_t)1, &buf, &buflen));
   223 		/* Administrator name. */
   224 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   225 		T(addstr(" (\n", (size_t)3, &buf, &buflen));
   226 		spaced = 0;
   228 		if ((edata - rdata) != 5*NS_INT32SZ)
   229 			goto formerr;
   231 		/* Serial number. */
   232 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   233 		T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
   234 		len = SPRINTF((tmp, "%lu", t));
   235 		T(addstr(tmp, (size_t)len, &buf, &buflen));
   236 		T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
   237 		T(addstr("; serial\n", (size_t)9, &buf, &buflen));
   238 		spaced = 0;
   240 		/* Refresh interval. */
   241 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   242 		T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
   243 		T(len = ns_format_ttl(t, buf, buflen));
   244 		addlen((size_t)len, &buf, &buflen);
   245 		T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
   246 		T(addstr("; refresh\n", (size_t)10, &buf, &buflen));
   247 		spaced = 0;
   249 		/* Retry interval. */
   250 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   251 		T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
   252 		T(len = ns_format_ttl(t, buf, buflen));
   253 		addlen((size_t)len, &buf, &buflen);
   254 		T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
   255 		T(addstr("; retry\n", (size_t)8, &buf, &buflen));
   256 		spaced = 0;
   258 		/* Expiry. */
   259 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   260 		T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
   261 		T(len = ns_format_ttl(t, buf, buflen));
   262 		addlen((size_t)len, &buf, &buflen);
   263 		T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
   264 		T(addstr("; expiry\n", (size_t)9, &buf, &buflen));
   265 		spaced = 0;
   267 		/* Minimum TTL. */
   268 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   269 		T(addstr("\t\t\t\t\t", (size_t)5, &buf, &buflen));
   270 		T(len = ns_format_ttl(t, buf, buflen));
   271 		addlen((size_t)len, &buf, &buflen);
   272 		T(addstr(" )", (size_t)2, &buf, &buflen));
   273 		T(spaced = addtab((size_t)len, (size_t)16, spaced, &buf, &buflen));
   274 		T(addstr("; minimum\n", (size_t)10, &buf, &buflen));
   276 		break;
   277 	    }
   279 	case ns_t_mx:
   280 	case ns_t_afsdb:
   281 	case ns_t_rt: {
   282 		u_int t;
   284 		if (rdlen < (size_t)NS_INT16SZ)
   285 			goto formerr;
   287 		/* Priority. */
   288 		t = ns_get16(rdata);
   289 		rdata += NS_INT16SZ;
   290 		len = SPRINTF((tmp, "%u ", t));
   291 		T(addstr(tmp, (size_t)len, &buf, &buflen));
   293 		/* Target. */
   294 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   296 		break;
   297 	    }
   299 	case ns_t_px: {
   300 		u_int t;
   302 		if (rdlen < (size_t)NS_INT16SZ)
   303 			goto formerr;
   305 		/* Priority. */
   306 		t = ns_get16(rdata);
   307 		rdata += NS_INT16SZ;
   308 		len = SPRINTF((tmp, "%u ", t));
   309 		T(addstr(tmp, (size_t)len, &buf, &buflen));
   311 		/* Name1. */
   312 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   313 		T(addstr(" ", (size_t)1, &buf, &buflen));
   315 		/* Name2. */
   316 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   318 		break;
   319 	    }
   321 	case ns_t_x25:
   322 		T(len = charstr(rdata, edata, &buf, &buflen));
   323 		if (len == 0)
   324 			goto formerr;
   325 		rdata += len;
   326 		break;
   328 	case ns_t_txt:
   329 		while (rdata < edata) {
   330 			T(len = charstr(rdata, edata, &buf, &buflen));
   331 			if (len == 0)
   332 				goto formerr;
   333 			rdata += len;
   334 			if (rdata < edata)
   335 				T(addstr(" ", (size_t)1, &buf, &buflen));
   336 		}
   337 		break;
   339 	case ns_t_nsap: {
   340 		char t[2+255*3];
   342 		(void) inet_nsap_ntoa((int)rdlen, rdata, t);
   343 		T(addstr(t, strlen(t), &buf, &buflen));
   344 		break;
   345 	    }
   347 	case ns_t_aaaa:
   348 		if (rdlen != (size_t)NS_IN6ADDRSZ)
   349 			goto formerr;
   350 		(void) inet_ntop(AF_INET6, rdata, buf, buflen);
   351 		addlen(strlen(buf), &buf, &buflen);
   352 		break;
   354 	case ns_t_loc: {
   355 		char t[255];
   357 		/* XXX protocol format checking? */
   358 		(void) loc_ntoa(rdata, t);
   359 		T(addstr(t, strlen(t), &buf, &buflen));
   360 		break;
   361 	    }
   363 	case ns_t_naptr: {
   364 		u_int order, preference;
   365 		char t[50];
   367 		if (rdlen < 2U*NS_INT16SZ)
   368 			goto formerr;
   370 		/* Order, Precedence. */
   371 		order = ns_get16(rdata);	rdata += NS_INT16SZ;
   372 		preference = ns_get16(rdata);	rdata += NS_INT16SZ;
   373 		len = SPRINTF((t, "%u %u ", order, preference));
   374 		T(addstr(t, (size_t)len, &buf, &buflen));
   376 		/* Flags. */
   377 		T(len = charstr(rdata, edata, &buf, &buflen));
   378 		if (len == 0)
   379 			goto formerr;
   380 		rdata += len;
   381 		T(addstr(" ", (size_t)1, &buf, &buflen));
   383 		/* Service. */
   384 		T(len = charstr(rdata, edata, &buf, &buflen));
   385 		if (len == 0)
   386 			goto formerr;
   387 		rdata += len;
   388 		T(addstr(" ", (size_t)1, &buf, &buflen));
   390 		/* Regexp. */
   391 		T(len = charstr(rdata, edata, &buf, &buflen));
   392 		if (len < 0)
   393 			return (-1);
   394 		if (len == 0)
   395 			goto formerr;
   396 		rdata += len;
   397 		T(addstr(" ", (size_t)1, &buf, &buflen));
   399 		/* Server. */
   400 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   401 		break;
   402 	    }
   404 	case ns_t_srv: {
   405 		u_int priority, weight, port;
   406 		char t[50];
   408 		if (rdlen < 3U*NS_INT16SZ)
   409 			goto formerr;
   411 		/* Priority, Weight, Port. */
   412 		priority = ns_get16(rdata);  rdata += NS_INT16SZ;
   413 		weight   = ns_get16(rdata);  rdata += NS_INT16SZ;
   414 		port     = ns_get16(rdata);  rdata += NS_INT16SZ;
   415 		len = SPRINTF((t, "%u %u %u ", priority, weight, port));
   416 		T(addstr(t, (size_t)len, &buf, &buflen));
   418 		/* Server. */
   419 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   420 		break;
   421 	    }
   423 	case ns_t_minfo:
   424 	case ns_t_rp:
   425 		/* Name1. */
   426 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   427 		T(addstr(" ", (size_t)1, &buf, &buflen));
   429 		/* Name2. */
   430 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   432 		break;
   434 	case ns_t_wks: {
   435 		int n, lcnt;
   437 		if (rdlen < 1U + NS_INT32SZ)
   438 			goto formerr;
   440 		/* Address. */
   441 		(void) inet_ntop(AF_INET, rdata, buf, buflen);
   442 		addlen(strlen(buf), &buf, &buflen);
   443 		rdata += NS_INADDRSZ;
   445 		/* Protocol. */
   446 		len = SPRINTF((tmp, " %u ( ", *rdata));
   447 		T(addstr(tmp, (size_t)len, &buf, &buflen));
   448 		rdata += NS_INT8SZ;
   450 		/* Bit map. */
   451 		n = 0;
   452 		lcnt = 0;
   453 		while (rdata < edata) {
   454 			u_int c = *rdata++;
   455 			do {
   456 				if (c & 0200) {
   457 					if (lcnt == 0) {
   458 						T(addstr("\n\t\t\t\t", (size_t)5,
   459 							 &buf, &buflen));
   460 						lcnt = 10;
   461 						spaced = 0;
   462 					}
   463 					len = SPRINTF((tmp, "%d ", n));
   464 					T(addstr(tmp, (size_t)len, &buf, &buflen));
   465 					lcnt--;
   466 				}
   467 				c <<= 1;
   468 			} while (++n & 07);
   469 		}
   470 		T(addstr(")", (size_t)1, &buf, &buflen));
   472 		break;
   473 	    }
   475 	case ns_t_key: {
   476 		char base64_key[NS_MD5RSA_MAX_BASE64];
   477 		u_int keyflags, protocol, algorithm, key_id;
   478 		const char *leader;
   479 		int n;
   481 		if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
   482 			goto formerr;
   484 		/* Key flags, Protocol, Algorithm. */
   485 #if !defined(MOZILLA_NECKO_EXCLUDE_CODE) && !defined(_LIBC)
   486 		key_id = dst_s_dns_key_id(rdata, edata-rdata);
   487 #else
   488 		key_id = 0;
   489 #endif
   490 		keyflags = ns_get16(rdata);  rdata += NS_INT16SZ;
   491 		protocol = *rdata++;
   492 		algorithm = *rdata++;
   493 		len = SPRINTF((tmp, "0x%04x %u %u",
   494 			       keyflags, protocol, algorithm));
   495 		T(addstr(tmp, (size_t)len, &buf, &buflen));
   497 		/* Public key data. */
   498 		len = b64_ntop(rdata, (size_t)(edata - rdata),
   499 			       base64_key, sizeof base64_key);
   500 		if (len < 0)
   501 			goto formerr;
   502 		if (len > 15) {
   503 			T(addstr(" (", (size_t)2, &buf, &buflen));
   504 			leader = "\n\t\t";
   505 			spaced = 0;
   506 		} else
   507 			leader = " ";
   508 		for (n = 0; n < len; n += 48) {
   509 			T(addstr(leader, strlen(leader), &buf, &buflen));
   510 			T(addstr(base64_key + n, (size_t)MIN(len - n, 48),
   511 				 &buf, &buflen));
   512 		}
   513 		if (len > 15)
   514 			T(addstr(" )", (size_t)2, &buf, &buflen));
   515 		n = SPRINTF((tmp, " ; key_tag= %u", key_id));
   516 		T(addstr(tmp, (size_t)n, &buf, &buflen));
   518 		break;
   519 	    }
   521 	case ns_t_sig: {
   522 		char base64_key[NS_MD5RSA_MAX_BASE64];
   523 		u_int typ, algorithm, labels, footprint;
   524 		const char *leader;
   525 		u_long t;
   526 		int n;
   528 		if (rdlen < 22U)
   529 			goto formerr;
   531 		/* Type covered, Algorithm, Label count, Original TTL. */
   532 	        typ = ns_get16(rdata);  rdata += NS_INT16SZ;
   533 		algorithm = *rdata++;
   534 		labels = *rdata++;
   535 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   536 		len = SPRINTF((tmp, "%s %d %d %lu ",
   537 			       p_type((int)typ), algorithm, labels, t));
   538 		T(addstr(tmp, (size_t)len, &buf, &buflen));
   539 		if (labels > (u_int)dn_count_labels(name))
   540 			goto formerr;
   542 		/* Signature expiry. */
   543 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   544 		len = SPRINTF((tmp, "%s ", p_secstodate(t)));
   545 		T(addstr(tmp, (size_t)len, &buf, &buflen));
   547 		/* Time signed. */
   548 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   549 		len = SPRINTF((tmp, "%s ", p_secstodate(t)));
   550 		T(addstr(tmp, (size_t)len, &buf, &buflen));
   552 		/* Signature Footprint. */
   553 		footprint = ns_get16(rdata);  rdata += NS_INT16SZ;
   554 		len = SPRINTF((tmp, "%u ", footprint));
   555 		T(addstr(tmp, (size_t)len, &buf, &buflen));
   557 		/* Signer's name. */
   558 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   560 		/* Signature. */
   561 		len = b64_ntop(rdata, (size_t)(edata - rdata),
   562 			       base64_key, sizeof base64_key);
   563 		if (len > 15) {
   564 			T(addstr(" (", (size_t)2, &buf, &buflen));
   565 			leader = "\n\t\t";
   566 			spaced = 0;
   567 		} else
   568 			leader = " ";
   569 		if (len < 0)
   570 			goto formerr;
   571 		for (n = 0; n < len; n += 48) {
   572 			T(addstr(leader, strlen(leader), &buf, &buflen));
   573 			T(addstr(base64_key + n, (size_t)MIN(len - n, 48),
   574 				 &buf, &buflen));
   575 		}
   576 		if (len > 15)
   577 			T(addstr(" )", (size_t)2, &buf, &buflen));
   578 		break;
   579 	    }
   581 	case ns_t_nxt: {
   582 		int n, c;
   584 		/* Next domain name. */
   585 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   587 		/* Type bit map. */
   588 		n = edata - rdata;
   589 		for (c = 0; c < n*8; c++)
   590 			if (NS_NXT_BIT_ISSET(c, rdata)) {
   591 				len = SPRINTF((tmp, " %s", p_type(c)));
   592 				T(addstr(tmp, (size_t)len, &buf, &buflen));
   593 			}
   594 		break;
   595 	    }
   597 	case ns_t_cert: {
   598 		u_int c_type, key_tag, alg;
   599 		int n;
   600 		unsigned int siz;
   601 		char base64_cert[8192], tmp1[40];
   602 		const char *leader;
   604 		c_type  = ns_get16(rdata); rdata += NS_INT16SZ;
   605 		key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
   606 		alg = (u_int) *rdata++;
   608 		len = SPRINTF((tmp1, "%d %d %d ", c_type, key_tag, alg));
   609 		T(addstr(tmp1, (size_t)len, &buf, &buflen));
   610 		siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
   611 		if (siz > sizeof(base64_cert) * 3/4) {
   612 			const char *str = "record too long to print";
   613 			T(addstr(str, strlen(str), &buf, &buflen));
   614 		}
   615 		else {
   616 			len = b64_ntop(rdata, (size_t)(edata-rdata),
   617 			    base64_cert, siz);
   619 			if (len < 0)
   620 				goto formerr;
   621 			else if (len > 15) {
   622 				T(addstr(" (", (size_t)2, &buf, &buflen));
   623 				leader = "\n\t\t";
   624 				spaced = 0;
   625 			}
   626 			else
   627 				leader = " ";
   629 			for (n = 0; n < len; n += 48) {
   630 				T(addstr(leader, strlen(leader),
   631 					 &buf, &buflen));
   632 				T(addstr(base64_cert + n, (size_t)MIN(len - n, 48),
   633 					 &buf, &buflen));
   634 			}
   635 			if (len > 15)
   636 				T(addstr(" )", (size_t)2, &buf, &buflen));
   637 		}
   638 		break;
   639 	    }
   641 	case ns_t_tkey: {
   642 		/* KJD - need to complete this */
   643 		u_long t;
   644 		int mode, err, keysize;
   646 		/* Algorithm name. */
   647 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   648 		T(addstr(" ", (size_t)1, &buf, &buflen));
   650 		/* Inception. */
   651 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   652 		len = SPRINTF((tmp, "%s ", p_secstodate(t)));
   653 		T(addstr(tmp, (size_t)len, &buf, &buflen));
   655 		/* Experation. */
   656 		t = ns_get32(rdata);  rdata += NS_INT32SZ;
   657 		len = SPRINTF((tmp, "%s ", p_secstodate(t)));
   658 		T(addstr(tmp, (size_t)len, &buf, &buflen));
   660 		/* Mode , Error, Key Size. */
   661 		/* Priority, Weight, Port. */
   662 		mode = ns_get16(rdata);  rdata += NS_INT16SZ;
   663 		err  = ns_get16(rdata);  rdata += NS_INT16SZ;
   664 		keysize  = ns_get16(rdata);  rdata += NS_INT16SZ;
   665 		len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize));
   666 		T(addstr(tmp, (size_t)len, &buf, &buflen));
   668 		/* XXX need to dump key, print otherdata length & other data */
   669 		break;
   670 	    }
   672 	case ns_t_tsig: {
   673 		/* BEW - need to complete this */
   674 		int n;
   676 		T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
   677 		T(addstr(" ", (size_t)1, &buf, &buflen));
   678 		rdata += 8; /* time */
   679 		n = ns_get16(rdata); rdata += INT16SZ;
   680 		rdata += n; /* sig */
   681 		n = ns_get16(rdata); rdata += INT16SZ; /* original id */
   682 		sprintf(buf, "%d", ns_get16(rdata));
   683 		rdata += INT16SZ;
   684 		addlen(strlen(buf), &buf, &buflen);
   685 		break;
   686 	    }
   688 	case ns_t_a6: {
   689 		struct in6_addr a;
   690 		int pbyte, pbit;
   692 		/* prefix length */
   693 		if (rdlen == 0U) goto formerr;
   694 		len = SPRINTF((tmp, "%d ", *rdata));
   695 		T(addstr(tmp, (size_t)len, &buf, &buflen));
   696 		pbit = *rdata;
   697 		if (pbit > 128) goto formerr;
   698 		pbyte = (pbit & ~7) / 8;
   699 		rdata++;
   701 		/* address suffix: provided only when prefix len != 128 */
   702 		if (pbit < 128) {
   703 			if (rdata + pbyte >= edata) goto formerr;
   704 			memset(&a, 0, sizeof(a));
   705 			memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte);
   706 			(void) inet_ntop(AF_INET6, &a, buf, buflen);
   707 			addlen(strlen(buf), &buf, &buflen);
   708 			rdata += sizeof(a) - pbyte;
   709 		}
   711 		/* prefix name: provided only when prefix len > 0 */
   712 		if (pbit == 0)
   713 			break;
   714 		if (rdata >= edata) goto formerr;
   715 		T(addstr(" ", (size_t)1, &buf, &buflen));
   716 		T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
   718 		break;
   719 	    }
   721 	case ns_t_opt: {
   722 		len = SPRINTF((tmp, "%u bytes", class));
   723 		T(addstr(tmp, (size_t)len, &buf, &buflen));
   724 		break;
   725 	    }
   727 	default:
   728 		comment = "unknown RR type";
   729 		goto hexify;
   730 	}
   731 	return (buf - obuf);
   732  formerr:
   733 	comment = "RR format error";
   734  hexify: {
   735 	int n, m;
   736 	char *p;
   738 	len = SPRINTF((tmp, "\\# %tu%s\t; %s", edata - rdata,
   739 		       rdlen != 0 ? " (" : "", comment));
   740 	T(addstr(tmp, (size_t)len, &buf, &buflen));
   741 	while (rdata < edata) {
   742 		p = tmp;
   743 		p += SPRINTF((p, "\n\t"));
   744 		spaced = 0;
   745 		n = MIN(16, edata - rdata);
   746 		for (m = 0; m < n; m++)
   747 			p += SPRINTF((p, "%02x ", rdata[m]));
   748 		T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen));
   749 		if (n < 16) {
   750 			T(addstr(")", (size_t)1, &buf, &buflen));
   751 			T(addtab((size_t)(p - tmp + 1), (size_t)48, spaced, &buf, &buflen));
   752 		}
   753 		p = tmp;
   754 		p += SPRINTF((p, "; "));
   755 		for (m = 0; m < n; m++)
   756 			*p++ = (isascii(rdata[m]) && isprint(rdata[m]))
   757 				? rdata[m]
   758 				: '.';
   759 		T(addstr(tmp, (size_t)(p - tmp), &buf, &buflen));
   760 		rdata += n;
   761 	}
   762 	return (buf - obuf);
   763     }
   764 }
   766 /* Private. */
   768 /*
   769  * size_t
   770  * prune_origin(name, origin)
   771  *	Find out if the name is at or under the current origin.
   772  * return:
   773  *	Number of characters in name before start of origin,
   774  *	or length of name if origin does not match.
   775  * notes:
   776  *	This function should share code with samedomain().
   777  */
   778 static size_t
   779 prune_origin(const char *name, const char *origin) {
   780 	const char *oname = name;
   782 	while (*name != '\0') {
   783 		if (origin != NULL && ns_samename(name, origin) == 1)
   784 			return (name - oname - (name > oname));
   785 		while (*name != '\0') {
   786 			if (*name == '\\') {
   787 				name++;
   788 				/* XXX need to handle \nnn form. */
   789 				if (*name == '\0')
   790 					break;
   791 			} else if (*name == '.') {
   792 				name++;
   793 				break;
   794 			}
   795 			name++;
   796 		}
   797 	}
   798 	return (name - oname);
   799 }
   801 /*
   802  * int
   803  * charstr(rdata, edata, buf, buflen)
   804  *	Format a <character-string> into the presentation buffer.
   805  * return:
   806  *	Number of rdata octets consumed
   807  *	0 for protocol format error
   808  *	-1 for output buffer error
   809  * side effects:
   810  *	buffer is advanced on success.
   811  */
   812 static int
   813 charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
   814 	const u_char *odata = rdata;
   815 	size_t save_buflen = *buflen;
   816 	char *save_buf = *buf;
   818 	if (addstr("\"", (size_t)1, buf, buflen) < 0)
   819 		goto enospc;
   820 	if (rdata < edata) {
   821 		int n = *rdata;
   823 		if (rdata + 1 + n <= edata) {
   824 			rdata++;
   825 			while (n-- > 0) {
   826 				if (strchr("\n\"\\", *rdata) != NULL)
   827 					if (addstr("\\", (size_t)1, buf, buflen) < 0)
   828 						goto enospc;
   829 				if (addstr((const char *)rdata, (size_t)1,
   830 					   buf, buflen) < 0)
   831 					goto enospc;
   832 				rdata++;
   833 			}
   834 		}
   835 	}
   836 	if (addstr("\"", (size_t)1, buf, buflen) < 0)
   837 		goto enospc;
   838 	return (rdata - odata);
   839  enospc:
   840 	errno = ENOSPC;
   841 	*buf = save_buf;
   842 	*buflen = save_buflen;
   843 	return (-1);
   844 }
   846 static int
   847 addname(const u_char *msg, size_t msglen,
   848 	const u_char **pp, const char *origin,
   849 	char **buf, size_t *buflen)
   850 {
   851 	size_t newlen, save_buflen = *buflen;
   852 	char *save_buf = *buf;
   853 	int n;
   855 	n = dn_expand(msg, msg + msglen, *pp, *buf, (int)*buflen);
   856 	if (n < 0)
   857 		goto enospc;	/* Guess. */
   858 	newlen = prune_origin(*buf, origin);
   859 	if (**buf == '\0') {
   860 		goto root;
   861 	} else if (newlen == 0U) {
   862 		/* Use "@" instead of name. */
   863 		if (newlen + 2 > *buflen)
   864 			goto enospc;        /* No room for "@\0". */
   865 		(*buf)[newlen++] = '@';
   866 		(*buf)[newlen] = '\0';
   867 	} else {
   868 		if (((origin == NULL || origin[0] == '\0') ||
   869 		    (origin[0] != '.' && origin[1] != '\0' &&
   870 		    (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') {
   871 			/* No trailing dot. */
   872  root:
   873 			if (newlen + 2 > *buflen)
   874 				goto enospc;	/* No room for ".\0". */
   875 			(*buf)[newlen++] = '.';
   876 			(*buf)[newlen] = '\0';
   877 		}
   878 	}
   879 	*pp += n;
   880 	addlen(newlen, buf, buflen);
   881 	**buf = '\0';
   882 	return (newlen);
   883  enospc:
   884 	errno = ENOSPC;
   885 	*buf = save_buf;
   886 	*buflen = save_buflen;
   887 	return (-1);
   888 }
   890 static void
   891 addlen(size_t len, char **buf, size_t *buflen) {
   892 	assert(len <= *buflen);
   893 	*buf += len;
   894 	*buflen -= len;
   895 }
   897 static int
   898 addstr(const char *src, size_t len, char **buf, size_t *buflen) {
   899 	if (len >= *buflen) {
   900 		errno = ENOSPC;
   901 		return (-1);
   902 	}
   903 	memcpy(*buf, src, len);
   904 	addlen(len, buf, buflen);
   905 	**buf = '\0';
   906 	return (0);
   907 }
   909 static int
   910 addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
   911 	size_t save_buflen = *buflen;
   912 	char *save_buf = *buf;
   913 	int t;
   915 	if (spaced || len >= target - 1) {
   916 		T(addstr("  ", (size_t)2, buf, buflen));
   917 		spaced = 1;
   918 	} else {
   919 		for (t = (target - len - 1) / 8; t >= 0; t--)
   920 			if (addstr("\t", (size_t)1, buf, buflen) < 0) {
   921 				*buflen = save_buflen;
   922 				*buf = save_buf;
   923 				return (-1);
   924 			}
   925 		spaced = 0;
   926 	}
   927 	return (spaced);
   928 }

mercurial