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