Home | History | Annotate | Download | only in smbsrv
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     27 
     28 #ifdef _KERNEL
     29 #include <sys/types.h>
     30 #include <sys/sunddi.h>
     31 #else
     32 #include <string.h>
     33 #endif
     34 #include <smbsrv/string.h>
     35 #include <smbsrv/ctype.h>
     36 #include <smbsrv/netbios.h>
     37 
     38 static int domainname_is_valid(char *domain_name);
     39 
     40 /*
     41  * Routines than support name compression.
     42  *
     43  *   The NetBIOS name representation in all NetBIOS packets (for NAME,
     44  *   SESSION, and DATAGRAM services) is defined in the Domain Name
     45  *   Service RFC 883[3] as "compressed" name messages.  This format is
     46  *   called "second-level encoding" in the section entitled
     47  *   "Representation of NetBIOS Names" in the Concepts and Methods
     48  *   document.
     49  *
     50  *   For ease of description, the first two paragraphs from page 31,
     51  *   the section titled "Domain name representation and compression",
     52  *   of RFC 883 are replicated here:
     53  *
     54  *        Domain names messages are expressed in terms of a sequence
     55  *        of labels.  Each label is represented as a one octet length
     56  *        field followed by that number of octets.  Since every domain
     57  *        name ends with the null label of the root, a compressed
     58  *        domain name is terminated by a length byte of zero.  The
     59  *        high order two bits of the length field must be zero, and
     60  *        the remaining six bits of the length field limit the label
     61  *        to 63 octets or less.
     62  *
     63  *        To simplify implementations, the total length of label
     64  *        octets and label length octets that make up a domain name is
     65  *        restricted to 255 octets or less.
     66  *
     67  *   The following is the uncompressed representation of the NetBIOS name
     68  *   "FRED ", which is the 4 ASCII characters, F, R, E, D, followed by 12
     69  *   space characters (0x20).  This name has the SCOPE_ID: "NETBIOS.COM"
     70  *
     71  *           EGFCEFEECACACACACACACACACACACACA.NETBIOS.COM
     72  *
     73  *   This uncompressed representation of names is called "first-level
     74  *   encoding" in the section entitled "Representation of NetBIOS Names"
     75  *   in the Concepts and Methods document.
     76  *
     77  *   The following is a pictographic representation of the compressed
     78  *   representation of the previous uncompressed Domain Name
     79  *   representation.
     80  *
     81  *                        1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
     82  *    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     83  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     84  *   |      0x20     |    E (0x45)   |    G (0x47)   |    F (0x46)   |
     85  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     86  *   |    C (0x43)   |    E (0x45)   |    F (0x46)   |    E (0x45)   |
     87  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     88  *   |    E (0x45)   |    C (0x43)   |    A (0x41)   |    C (0x43)   |
     89  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     90  *   |    A (0x41)   |    C (0x43)   |    A (0x41)   |    C (0x43)   |
     91  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     92  *   |    A (0x41)   |    C (0x43)   |    A (0x41)   |    C (0x43)   |
     93  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     94  *   |    A (0x41)   |    C (0x43)   |    A (0x41)   |    C (0x43)   |
     95  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     96  *   |    A (0x41)   |    C (0x43)   |    A (0x41)   |    C (0x43)   |
     97  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     98  *   |    A (0x41)   |    C (0x43)   |    A (0x41)   |    C (0x43)   |
     99  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    100  *   |    A (0X41)   |      0x07     |    N (0x4E)   |    E (0x45)   |
    101  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    102  *   |    T (0x54)   |    B (0x42)   |    I (0x49)   |    O (0x4F)   |
    103  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    104  *   |    S (0x53)   |      0x03     |    C (0x43)   |    O (0x4F)   |
    105  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    106  *   |    M (0x4D)   |      0x00     |
    107  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    108  *
    109  *   Each section of a domain name is called a label [7 (page 31)].  A
    110  *   label can be a maximum of 63 bytes.  The first byte of a label in
    111  *   compressed representation is the number of bytes in the label.  For
    112  *   the above example, the first 0x20 is the number of bytes in the
    113  *   left-most label, EGFCEFEECACACACACACACACACACACACA, of the domain
    114  *   name.  The bytes following the label length count are the characters
    115  *   of the label.  The following labels are in sequence after the first
    116  *   label, which is the encoded NetBIOS name, until a zero (0x00) length
    117  *   count.  The zero length count represents the root label, which is
    118  *   always null.
    119  *
    120  *   A label length count is actually a 6-bit field in the label length
    121  *   field.  The most significant 2 bits of the field, bits 7 and 6, are
    122  *   flags allowing an escape from the above compressed representation.
    123  *   If bits 7 and 6 are both set (11), the following 14 bits are an
    124  *   offset pointer into the full message to the actual label string from
    125  *   another domain name that belongs in this name.  This label pointer
    126  *   allows for a further compression of a domain name in a packet.
    127  *
    128  *   NetBIOS implementations can only use label string pointers in Name
    129  *   Service packets.  They cannot be used in Session or Datagram Service
    130  *   packets.
    131  *
    132  *   The other two possible values for bits 7 and 6 (01 and 10) of a label
    133  *   length field are reserved for future use by RFC 883[2 (page 32)].
    134  *
    135  *   Note that the first octet of a compressed name must contain one of
    136  *   the following bit patterns.  (An "x" indicates a bit whose value may
    137  *   be either 0 or 1.):
    138  *
    139  *           00100000 -  Netbios name, length must be 32 (decimal)
    140  *           11xxxxxx -  Label string pointer
    141  *           10xxxxxx -  Reserved
    142  *           01xxxxxx -  Reserved
    143  */
    144 
    145 /*
    146  * netbios_first_level_name_encode
    147  *
    148  * Put test description here.
    149  *
    150  * Inputs:
    151  *	char *	in	-> Name to encode
    152  *	char *	out	-> Buffer to encode into.
    153  *	int	length	-> # of bytes to encode.
    154  *
    155  * Returns:
    156  *	Nothing
    157  */
    158 int
    159 netbios_first_level_name_encode(unsigned char *name, unsigned char *scope,
    160     unsigned char *out, int max_out)
    161 {
    162 	unsigned char	ch, len;
    163 	unsigned char	 *in;
    164 	unsigned char	 *lp;
    165 	unsigned char	 *op = out;
    166 
    167 	if (max_out < 0x21)
    168 		return (-1);
    169 
    170 	in = name;
    171 	*op++ = 0x20;
    172 	for (len = 0; len < NETBIOS_NAME_SZ; len++) {
    173 		ch = *in++;
    174 		*op++ = 'A' + ((ch >> 4) & 0xF);
    175 		*op++ = 'A' + ((ch) & 0xF);
    176 	}
    177 
    178 	max_out -= 0x21;
    179 
    180 	in = scope;
    181 	len = 0;
    182 	lp = op++;
    183 	while (((ch = *in++) != 0) && (max_out-- > 1)) {
    184 		if (ch == 0) {
    185 			if ((*lp = len) != 0)
    186 				*op++ = 0;
    187 			break;
    188 		}
    189 		if (ch == '.') {
    190 			*lp = len;
    191 			lp = op++;
    192 			len = 0;
    193 		} else {
    194 			*op++ = ch;
    195 			len++;
    196 		}
    197 	}
    198 	*lp = len;
    199 	if (len != 0)
    200 		*op = 0;
    201 
    202 	/*LINTED E_PTRDIFF_OVERFLOW*/
    203 	return (op - out);
    204 }
    205 
    206 /*
    207  * smb_first_level_name_decode
    208  *
    209  * The null terminated string "in" is the name to decode. The output
    210  * is placed in the name_entry structure "name".
    211  *
    212  * The scope field is a series of length designated labels as described
    213  * in the "Domain name representation and compression" section of RFC883.
    214  * The two high order two bits of the length field must be zero, the
    215  * remaining six bits contain the field length. The total length of the
    216  * domain name is restricted to 255 octets but note that the trailing
    217  * root label and its dot are not printed. When converting the labels,
    218  * the length fields are replaced by dots.
    219  *
    220  * Returns the number of bytes scanned or -1 to indicate an error.
    221  */
    222 int
    223 netbios_first_level_name_decode(char *in, char *name, char *scope)
    224 {
    225 	unsigned int	length, bytes;
    226 	char		c1, c2;
    227 	char		*cp;
    228 	char		*out;
    229 
    230 	cp = in;
    231 
    232 	if ((length = *cp++) != 0x20) {
    233 		return (-1);
    234 	}
    235 
    236 	out = name;
    237 	while (length > 0) {
    238 		c1 = *cp++;
    239 		c2 = *cp++;
    240 
    241 		if ('A' <= c1 && c1 <= 'P' && 'A' <= c2 && c2 <= 'P') {
    242 			c1 -= 'A';
    243 			c2 -= 'A';
    244 			*out++ = (c1 << 4) | (c2);
    245 		} else {
    246 			return (-1);		/* conversion error */
    247 		}
    248 		length -= 2;
    249 	}
    250 
    251 	out = scope;
    252 	bytes = 0;
    253 	for (length = *cp++; length != 0; length = *cp++) {
    254 		if ((length & 0xc0) != 0x00) {
    255 			/*
    256 			 * This is a pointer or a reserved field. If it's
    257 			 * a pointer (16-bits) we have to skip the next byte.
    258 			 */
    259 			if ((length & 0xc0) == 0xc0) {
    260 				cp++;
    261 				continue;
    262 			}
    263 		}
    264 
    265 		/*
    266 		 * Replace the length with a '.', except for the first one.
    267 		 */
    268 		if (out != scope) {
    269 			*out++ = '.';
    270 			bytes++;
    271 		}
    272 
    273 		while (length-- > 0) {
    274 			if (bytes++ >= (NETBIOS_DOMAIN_NAME_MAX - 1)) {
    275 				return (-1);
    276 			}
    277 			*out++ = *cp++;
    278 		}
    279 	}
    280 	*out = 0;
    281 
    282 	/*
    283 	 * We are supposed to preserve all 8-bits of the domain name
    284 	 * but due to the single byte representation in the name cache
    285 	 * and UTF-8 encoding everywhere else, we restrict domain names
    286 	 * to Appendix 1 - Domain Name Syntax Specification in RFC883.
    287 	 */
    288 	if (domainname_is_valid(scope))	{
    289 		(void) utf8_strupr(scope);
    290 		/*LINTED E_PTRDIFF_OVERFLOW*/
    291 		return (cp - in);
    292 	}
    293 
    294 	scope[0] = '\0';
    295 	return (-1);
    296 }
    297 
    298 /*
    299  * smb_netbios_name_isvalid
    300  *
    301  * This function is provided to be used by session service
    302  * which runs in kernel in order to hide name_entry definition.
    303  *
    304  * It returns the decoded name in the provided buffer as 'out'
    305  * if it's not null.
    306  *
    307  * Returns 0 if decode fails, 1 if it succeeds.
    308  */
    309 int
    310 netbios_name_isvalid(char *in, char *out)
    311 {
    312 	char name[NETBIOS_NAME_SZ];
    313 	char scope[NETBIOS_DOMAIN_NAME_MAX];
    314 
    315 	if (netbios_first_level_name_decode(in, name, scope) < 0)
    316 		return (0);
    317 
    318 	if (out)
    319 		(void) strlcpy(out, name, NETBIOS_NAME_SZ);
    320 
    321 	return (1);
    322 }
    323 
    324 /*
    325  * Characters that we allow in DNS domain names, in addition to
    326  * alphanumeric characters. This is not quite consistent with
    327  * RFC883. This is global so that it can be patched if there is
    328  * a need to change the valid characters in the field.
    329  */
    330 unsigned char *dns_allowed = (unsigned char *)"-_";
    331 
    332 /*
    333  * dns_is_allowed
    334  *
    335  * Check the dns_allowed characters and return true (1) if the character
    336  * is in the table. Otherwise return false (0).
    337  */
    338 static int
    339 dns_is_allowed(unsigned char c)
    340 {
    341 	unsigned char *p = dns_allowed;
    342 
    343 	while (*p) {
    344 		if (c == *p++)
    345 			return (1);
    346 	}
    347 
    348 	return (0);
    349 }
    350 
    351 
    352 /*
    353  * domainname_is_valid
    354  *
    355  * Check the specified domain name for mostly compliance with RFC883
    356  * Appendix 1. Names may contain alphanumeric characters, hyphens,
    357  * underscores and dots. The first character after a dot must be an
    358  * alphabetic character. RFC883 doesn't mention underscores but we
    359  * allow it due to common use, and we don't check that labels end
    360  * with an alphanumeric character.
    361  *
    362  * Returns true (1) if the name is valid. Otherwise returns false (0).
    363  */
    364 static int
    365 domainname_is_valid(char *domain_name)
    366 {
    367 	char *name;
    368 	int first_char = 1;
    369 
    370 	if (domain_name == 0)
    371 		return (0);
    372 
    373 	for (name = domain_name; *name != 0; ++name) {
    374 		if (*name == '.') {
    375 			first_char = 1;
    376 			continue;
    377 		}
    378 
    379 		if (first_char)	{
    380 			if (mts_isalpha_ascii(*name) == 0)
    381 				return (0);
    382 
    383 			first_char = 0;
    384 			continue;
    385 		}
    386 
    387 		if (mts_isalnum_ascii(*name) || dns_is_allowed(*name))
    388 			continue;
    389 
    390 		return (0);
    391 	}
    392 
    393 	return (1);
    394 }
    395