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 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 *
25 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
26 */
27
28 /*
29 * This module defines generic functions to map Native OS and Native
30 * LanMan names to values.
31 */
32
33 #if defined(_KERNEL) || defined(_FAKE_KERNEL)
34 #include <sys/types.h>
35 #include <sys/sunddi.h>
36 #else
37 #include <string.h>
38 #endif
39 #include <smbsrv/string.h>
40 #include <smbsrv/smbinfo.h>
41
42 typedef struct smb_native {
43 int sn_value;
44 const char *sn_name;
45 } smb_native_t;
46
47 /*
48 * smbnative_os_value
49 *
50 * Return the appropriate native OS value for the specified native OS name.
51 *
52 * Example OS values used by Windows:
53 *
54 * Windows 4.0, Windows NT, Windows NT 4.0
55 * Windows 5.0, Windows 5.1
56 * Windows 2000, Windows 2000 5.0, Windows 2000 5.1
57 * Windows 2002
58 * Windows .NET
59 * Windows Server 2003
60 * Windows XP
61 *
62 * Windows 2000 server: "Windows 2000 2195"
63 * Windows XP Professional client: "Windows 2002 2543"
64 * Windows XP PDC server: "Windows 5.1"
65 * Windows .Net: "Windows .NET 3621"
66 * Windows .Net: "Windows .NET 3718"
67 *
68 * DAVE (Thursby Software: CIFS for MacOS) uses "MacOS", sometimes with a
69 * version number appended, i.e. "MacOS 8.5.1". We treat DAVE like NT 4.0
70 * except for the cases that DAVE clients set 'watch tree' flag in notify
71 * change requests.
72 *
73 * Samba reports UNIX as its Native OS, which we can map to NT 4.0.
74 */
75 int
smbnative_os_value(const char * native_os)76 smbnative_os_value(const char *native_os)
77 {
78 static smb_native_t os_table[] = {
79 { NATIVE_OS_WINNT, "Windows NT 4.0" },
80 { NATIVE_OS_WINNT, "Windows NT" },
81 { NATIVE_OS_WIN95, "Windows 4.0" },
82 { NATIVE_OS_WIN2000, "Windows 5.0" },
83 { NATIVE_OS_WIN2000, "Windows 5.1" },
84 { NATIVE_OS_WIN2000, "Windows 2000" },
85 { NATIVE_OS_WIN2000, "Windows 2002" },
86 { NATIVE_OS_WIN2000, "Windows .NET" },
87 { NATIVE_OS_WIN2000, "Windows Server" },
88 { NATIVE_OS_WIN2000, "Windows XP" },
89 { NATIVE_OS_WINNT, "UNIX" },
90 { NATIVE_OS_MACOS, "MacOS" }
91 };
92
93 int i;
94 int len;
95 const char *name;
96
97 if (native_os == NULL)
98 return (NATIVE_OS_UNKNOWN);
99
100 /*
101 * Windows Vista sends an empty native OS string.
102 */
103 if (*native_os == '\0')
104 return (NATIVE_OS_WIN2000);
105
106 for (i = 0; i < sizeof (os_table)/sizeof (os_table[0]); ++i) {
107 name = os_table[i].sn_name;
108 len = strlen(name);
109
110 if (smb_strcasecmp(name, native_os, len) == 0)
111 return (os_table[i].sn_value);
112 }
113
114 return (NATIVE_OS_UNKNOWN);
115 }
116
117 /*
118 * smbnative_lm_value
119 *
120 * Return the appropriate native LanMan value for the specified native
121 * LanMan name. There's an alignment problem in some packets from some
122 * clients that means we can miss the first character, so we do an
123 * additional check starting from the second character.
124 *
125 * Example LanMan values:
126 *
127 * NT LAN Manager 4.0
128 * Windows 4.0
129 * Windows NT, Windows NT 4.0
130 * Windows 2000 LAN Manager
131 * Windows 2000, Windows 2000 5.0, Windows 2000 5.1
132 * Windows 2002, Windows 2002 5.1
133 * Windows .NET, Windows .NET 5.2
134 * Windows Server 2003
135 * Windows XP
136 * NETSMB (Solaris CIFS client)
137 * DAVE (Thursby Software: CIFS for MacOS)
138 * Samba
139 */
140 int
smbnative_lm_value(const char * native_lm)141 smbnative_lm_value(const char *native_lm)
142 {
143 static smb_native_t lm_table[] = {
144 { NATIVE_LM_NT, "NT LAN Manager 4.0" },
145 { NATIVE_LM_NT, "Windows NT" },
146 { NATIVE_LM_NT, "Windows 4.0" },
147 { NATIVE_LM_NT, "DAVE" }
148 };
149
150 int i;
151 int len;
152 const char *name;
153
154 /*
155 * Windows Vista sends an empty native LM string.
156 */
157 if (native_lm == NULL || *native_lm == '\0')
158 return (NATIVE_LM_WIN2000);
159
160 for (i = 0; i < sizeof (lm_table)/sizeof (lm_table[0]); ++i) {
161 name = lm_table[i].sn_name;
162 len = strlen(name);
163
164 if ((smb_strcasecmp(name, native_lm, len) == 0) ||
165 (smb_strcasecmp(&name[1], native_lm, len - 1) == 0)) {
166 return (lm_table[i].sn_value);
167 }
168 }
169
170 return (NATIVE_LM_WIN2000);
171 }
172
173 /*
174 * smbnative_pdc_value
175 *
176 * This function is called when libsmbrdr connects to a PDC.
177 * The PDC type is derived from the Native LanMan string.
178 * The PDC value will default to PDC_WIN2000.
179 *
180 * Example strings:
181 *
182 * NT LAN Manager 4.0
183 * Windows 4.0, Windows NT, Windows NT 4.0
184 * Windows 2000 LAN Manager
185 * Windows 2000, Windows 2000 5.0, Windows 2000 5.1
186 * Windows 2002, Windows 2002 5.1
187 * Windows .NET, Windows .NET 5.2
188 * Samba
189 * DAVE
190 */
191 int
smbnative_pdc_value(const char * native_lm)192 smbnative_pdc_value(const char *native_lm)
193 {
194 static smb_native_t pdc_table[] = {
195 { PDC_WINNT, "NT LAN Manager 4.0" },
196 { PDC_WINNT, "Windows NT 4.0" },
197 { PDC_WINNT, "Windows NT" },
198 { PDC_WINNT, "Windows 4.0" },
199 { PDC_WINNT, "DAVE" },
200 { PDC_SAMBA, "Samba" }
201 };
202
203 int i;
204 int len;
205 const char *name;
206
207 if (native_lm == NULL || *native_lm == '\0')
208 return (PDC_WIN2000);
209
210 for (i = 0; i < sizeof (pdc_table)/sizeof (pdc_table[0]); ++i) {
211 name = pdc_table[i].sn_name;
212 len = strlen(name);
213
214 if ((smb_strcasecmp(name, native_lm, len) == 0) ||
215 (smb_strcasecmp(&name[1], native_lm, len - 1) == 0)) {
216 return (pdc_table[i].sn_value);
217 }
218 }
219
220 return (PDC_WIN2000);
221 }
222
223 /*
224 * Returns the native OS string for the given OS version.
225 * If no match is found the string for Windows 2000 is returned.
226 */
227 const char *
smbnative_os_str(smb_version_t * version)228 smbnative_os_str(smb_version_t *version)
229 {
230 int i;
231
232 static smb_native_t osstr_table[] = {
233 { SMB_MAJOR_NT, "Windows NT" },
234 { SMB_MAJOR_2000, "Windows 2000" },
235 { SMB_MAJOR_XP, "Windows XP" },
236 { SMB_MAJOR_2003, "Windows Server 2003" },
237 { SMB_MAJOR_VISTA, "" },
238 { SMB_MAJOR_2008, "" },
239 { SMB_MAJOR_2008R2, "" }
240 };
241
242 for (i = 0; i < sizeof (osstr_table)/sizeof (osstr_table[0]); ++i) {
243 if (version->sv_major == osstr_table[i].sn_value)
244 return (osstr_table[i].sn_name);
245 }
246
247 return (osstr_table[1].sn_name);
248 }
249
250 /*
251 * Returns the native Lanman string for the given OS version.
252 * If no match is found the string for Windows 2000 is returned.
253 */
254 const char *
smbnative_lm_str(smb_version_t * version)255 smbnative_lm_str(smb_version_t *version)
256 {
257 int i;
258
259 static smb_native_t lmstr_table[] = {
260 { SMB_MAJOR_NT, "NT LAN Manager 4.0" },
261 { SMB_MAJOR_2000, "Windows 2000 LAN Manager" },
262 { SMB_MAJOR_XP, "Windows 2002 5.1" },
263 { SMB_MAJOR_2003, "Windows Server 2003 5.2" },
264 { SMB_MAJOR_VISTA, "" },
265 { SMB_MAJOR_2008, "" },
266 { SMB_MAJOR_2008R2, "" }
267 };
268
269 for (i = 0; i < sizeof (lmstr_table)/sizeof (lmstr_table[0]); ++i) {
270 if (version->sv_major == lmstr_table[i].sn_value)
271 return (lmstr_table[i].sn_name);
272 }
273
274 return (lmstr_table[1].sn_name);
275 }
276