getconf: don't include xpg4 bits, gcc7 includes xpg6 bits for us
[unleashed.git] / usr / src / common / smbsrv / smb_netbios_util.c
blob375239a0cf9272c57615c0a8b8723f0e85e729e6
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
28 #if defined(_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/netbios.h>
38 * Routines than support name compression.
40 * The NetBIOS name representation in all NetBIOS packets (for NAME,
41 * SESSION, and DATAGRAM services) is defined in the Domain Name
42 * Service RFC 883[3] as "compressed" name messages. This format is
43 * called "second-level encoding" in the section entitled
44 * "Representation of NetBIOS Names" in the Concepts and Methods
45 * document.
47 * For ease of description, the first two paragraphs from page 31,
48 * the section titled "Domain name representation and compression",
49 * of RFC 883 are replicated here:
51 * Domain names messages are expressed in terms of a sequence
52 * of labels. Each label is represented as a one octet length
53 * field followed by that number of octets. Since every domain
54 * name ends with the null label of the root, a compressed
55 * domain name is terminated by a length byte of zero. The
56 * high order two bits of the length field must be zero, and
57 * the remaining six bits of the length field limit the label
58 * to 63 octets or less.
60 * To simplify implementations, the total length of label
61 * octets and label length octets that make up a domain name is
62 * restricted to 255 octets or less.
64 * The following is the uncompressed representation of the NetBIOS name
65 * "FRED ", which is the 4 ASCII characters, F, R, E, D, followed by 12
66 * space characters (0x20). This name has the SCOPE_ID: "NETBIOS.COM"
68 * EGFCEFEECACACACACACACACACACACACA.NETBIOS.COM
70 * This uncompressed representation of names is called "first-level
71 * encoding" in the section entitled "Representation of NetBIOS Names"
72 * in the Concepts and Methods document.
74 * The following is a pictographic representation of the compressed
75 * representation of the previous uncompressed Domain Name
76 * representation.
78 * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
79 * 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
80 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
81 * | 0x20 | E (0x45) | G (0x47) | F (0x46) |
82 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
83 * | C (0x43) | E (0x45) | F (0x46) | E (0x45) |
84 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
85 * | E (0x45) | C (0x43) | A (0x41) | C (0x43) |
86 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
87 * | A (0x41) | C (0x43) | A (0x41) | C (0x43) |
88 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
89 * | A (0x41) | C (0x43) | A (0x41) | C (0x43) |
90 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
91 * | A (0x41) | C (0x43) | A (0x41) | C (0x43) |
92 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
93 * | A (0x41) | C (0x43) | A (0x41) | C (0x43) |
94 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
95 * | A (0x41) | C (0x43) | A (0x41) | C (0x43) |
96 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
97 * | A (0X41) | 0x07 | N (0x4E) | E (0x45) |
98 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99 * | T (0x54) | B (0x42) | I (0x49) | O (0x4F) |
100 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101 * | S (0x53) | 0x03 | C (0x43) | O (0x4F) |
102 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
103 * | M (0x4D) | 0x00 |
104 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
106 * Each section of a domain name is called a label [7 (page 31)]. A
107 * label can be a maximum of 63 bytes. The first byte of a label in
108 * compressed representation is the number of bytes in the label. For
109 * the above example, the first 0x20 is the number of bytes in the
110 * left-most label, EGFCEFEECACACACACACACACACACACACA, of the domain
111 * name. The bytes following the label length count are the characters
112 * of the label. The following labels are in sequence after the first
113 * label, which is the encoded NetBIOS name, until a zero (0x00) length
114 * count. The zero length count represents the root label, which is
115 * always null.
117 * A label length count is actually a 6-bit field in the label length
118 * field. The most significant 2 bits of the field, bits 7 and 6, are
119 * flags allowing an escape from the above compressed representation.
120 * If bits 7 and 6 are both set (11), the following 14 bits are an
121 * offset pointer into the full message to the actual label string from
122 * another domain name that belongs in this name. This label pointer
123 * allows for a further compression of a domain name in a packet.
125 * NetBIOS implementations can only use label string pointers in Name
126 * Service packets. They cannot be used in Session or Datagram Service
127 * packets.
129 * The other two possible values for bits 7 and 6 (01 and 10) of a label
130 * length field are reserved for future use by RFC 883[2 (page 32)].
132 * Note that the first octet of a compressed name must contain one of
133 * the following bit patterns. (An "x" indicates a bit whose value may
134 * be either 0 or 1.):
136 * 00100000 - Netbios name, length must be 32 (decimal)
137 * 11xxxxxx - Label string pointer
138 * 10xxxxxx - Reserved
139 * 01xxxxxx - Reserved
143 * netbios_first_level_name_encode
145 * Put test description here.
147 * Inputs:
148 * char * in -> Name to encode
149 * char * out -> Buffer to encode into.
150 * int length -> # of bytes to encode.
152 * Returns:
153 * Nothing
156 netbios_first_level_name_encode(unsigned char *name, unsigned char *scope,
157 unsigned char *out, int max_out)
159 unsigned char ch, len;
160 unsigned char *in;
161 unsigned char *lp;
162 unsigned char *op = out;
164 if (max_out < 0x21)
165 return (-1);
167 in = name;
168 *op++ = 0x20;
169 for (len = 0; len < NETBIOS_NAME_SZ; len++) {
170 ch = *in++;
171 *op++ = 'A' + ((ch >> 4) & 0xF);
172 *op++ = 'A' + ((ch) & 0xF);
175 max_out -= 0x21;
177 in = scope;
178 len = 0;
179 lp = op++;
180 while (((ch = *in++) != 0) && (max_out-- > 1)) {
181 if (ch == 0) {
182 if ((*lp = len) != 0)
183 *op++ = 0;
184 break;
186 if (ch == '.') {
187 *lp = len;
188 lp = op++;
189 len = 0;
190 } else {
191 *op++ = ch;
192 len++;
195 *lp = len;
196 if (len != 0)
197 *op = 0;
199 /*LINTED E_PTRDIFF_OVERFLOW*/
200 return (op - out);
204 * smb_first_level_name_decode
206 * The null terminated string "in" is the name to decode. The output
207 * is placed in the name_entry structure "name".
209 * The scope field is a series of length designated labels as described
210 * in the "Domain name representation and compression" section of RFC883.
211 * The two high order two bits of the length field must be zero, the
212 * remaining six bits contain the field length. The total length of the
213 * domain name is restricted to 255 octets but note that the trailing
214 * root label and its dot are not printed. When converting the labels,
215 * the length fields are replaced by dots.
217 * Returns the number of bytes scanned or -1 to indicate an error.
220 netbios_first_level_name_decode(char *in, char *name, char *scope)
222 unsigned int length;
223 char c1, c2;
224 char *cp;
225 char *out;
227 cp = in;
229 if ((length = *cp++) != 0x20) {
230 return (-1);
233 out = name;
234 while (length > 0) {
235 c1 = *cp++;
236 c2 = *cp++;
238 if ('A' <= c1 && c1 <= 'P' && 'A' <= c2 && c2 <= 'P') {
239 c1 -= 'A';
240 c2 -= 'A';
241 *out++ = (c1 << 4) | (c2);
242 } else {
243 return (-1); /* conversion error */
245 length -= 2;
249 * Don't bother decoding the scope. Not supported.
251 if ((length = *cp++) != 0)
252 return (-1);
253 scope[0] = '\0';
255 /*LINTED E_PTRDIFF_OVERFLOW*/
256 return (cp - in);
260 * smb_netbios_name_isvalid
262 * This function is provided to be used by session service
263 * which runs in kernel in order to hide name_entry definition.
265 * It returns the decoded name in the provided buffer as 'out'
266 * if it's not null.
268 * Returns 0 if decode fails, 1 if it succeeds.
271 netbios_name_isvalid(char *in, char *out)
273 char name[NETBIOS_NAME_SZ];
274 char scope[NETBIOS_DOMAIN_NAME_MAX];
276 if (netbios_first_level_name_decode(in, name, scope) < 0)
277 return (0);
279 if (out)
280 (void) strlcpy(out, name, NETBIOS_NAME_SZ);
282 return (1);