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