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