xref: /titanic_41/usr/src/common/smbsrv/smb_native.c (revision fc724630b14603e4c1147df68b7bf45f7de7431f)
1da6c28aaSamw /*
2da6c28aaSamw  * CDDL HEADER START
3da6c28aaSamw  *
4da6c28aaSamw  * The contents of this file are subject to the terms of the
5da6c28aaSamw  * Common Development and Distribution License (the "License").
6da6c28aaSamw  * You may not use this file except in compliance with the License.
7da6c28aaSamw  *
8da6c28aaSamw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw  * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw  * See the License for the specific language governing permissions
11da6c28aaSamw  * and limitations under the License.
12da6c28aaSamw  *
13da6c28aaSamw  * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw  * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw  * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw  * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw  *
19da6c28aaSamw  * CDDL HEADER END
20da6c28aaSamw  */
21da6c28aaSamw /*
22*fc724630SAlan Wright  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23da6c28aaSamw  * Use is subject to license terms.
24da6c28aaSamw  */
25da6c28aaSamw 
26da6c28aaSamw /*
27da6c28aaSamw  * This module defines generic functions to map Native OS and Native
28da6c28aaSamw  * LanMan names to values.
29da6c28aaSamw  */
30da6c28aaSamw 
31da6c28aaSamw #ifdef _KERNEL
32da6c28aaSamw #include <sys/types.h>
33da6c28aaSamw #include <sys/sunddi.h>
34da6c28aaSamw #else
35da6c28aaSamw #include <string.h>
36da6c28aaSamw #endif
37da6c28aaSamw #include <smbsrv/string.h>
38da6c28aaSamw #include <smbsrv/smbinfo.h>
39da6c28aaSamw 
40*fc724630SAlan Wright typedef struct smb_native {
41*fc724630SAlan Wright 	int sn_value;
42*fc724630SAlan Wright 	const char *sn_name;
43*fc724630SAlan Wright } smb_native_t;
44*fc724630SAlan Wright 
45da6c28aaSamw /*
46da6c28aaSamw  * smbnative_os_value
47da6c28aaSamw  *
48da6c28aaSamw  * Return the appropriate native OS value for the specified native OS name.
49da6c28aaSamw  *
50*fc724630SAlan Wright  * Example OS values used by Windows:
51*fc724630SAlan Wright  *
52*fc724630SAlan Wright  *	Windows 4.0, Windows NT, Windows NT 4.0
53*fc724630SAlan Wright  *	Windows 5.0, Windows 5.1
54*fc724630SAlan Wright  *	Windows 2000, Windows 2000 5.0, Windows 2000 5.1
55*fc724630SAlan Wright  *	Windows 2002
56*fc724630SAlan Wright  *	Windows .NET
57*fc724630SAlan Wright  *	Windows Server 2003
58*fc724630SAlan Wright  *	Windows XP
59*fc724630SAlan Wright  *
60da6c28aaSamw  * Windows 2000 server:            "Windows 2000 2195"
61da6c28aaSamw  * Windows XP Professional client: "Windows 2002 2543"
62da6c28aaSamw  * Windows XP PDC server:          "Windows 5.1"
63da6c28aaSamw  * Windows .Net:                   "Windows .NET 3621"
64da6c28aaSamw  * Windows .Net:                   "Windows .NET 3718"
65da6c28aaSamw  *
66da6c28aaSamw  * DAVE (Thursby Software: CIFS for MacOS) uses "MacOS", sometimes with a
67da6c28aaSamw  * version number appended, i.e. "MacOS 8.5.1". We treat DAVE like NT 4.0
68da6c28aaSamw  * except for the cases that DAVE clients set 'watch tree' flag in notify
69da6c28aaSamw  * change requests.
70da6c28aaSamw  *
71da6c28aaSamw  * Samba reports UNIX as its Native OS, which we can map to NT 4.0.
72da6c28aaSamw  */
73da6c28aaSamw int
74*fc724630SAlan Wright smbnative_os_value(const char *native_os)
75da6c28aaSamw {
76*fc724630SAlan Wright 	static smb_native_t os_table[] = {
77da6c28aaSamw 		{ NATIVE_OS_WINNT,	"Windows NT 4.0"	},
78da6c28aaSamw 		{ NATIVE_OS_WINNT,	"Windows NT"		},
79da6c28aaSamw 		{ NATIVE_OS_WIN95,	"Windows 4.0"		},
80da6c28aaSamw 		{ NATIVE_OS_WIN2000,	"Windows 5.0"		},
81da6c28aaSamw 		{ NATIVE_OS_WIN2000,	"Windows 5.1"		},
82da6c28aaSamw 		{ NATIVE_OS_WIN2000,	"Windows 2000 5.0"	},
83da6c28aaSamw 		{ NATIVE_OS_NT5_1,	"Windows 2000 5.1"	},
84da6c28aaSamw 		{ NATIVE_OS_WIN2000,	"Windows 2000"		},
85da6c28aaSamw 		{ NATIVE_OS_WIN2000,	"Windows 2002"		},
86da6c28aaSamw 		{ NATIVE_OS_WIN2000,	"Windows .NET"		},
87*fc724630SAlan Wright 		{ NATIVE_OS_WIN2000,	"Windows Server"	},
88da6c28aaSamw 		{ NATIVE_OS_WIN2000,	"Windows XP"		},
89da6c28aaSamw 		{ NATIVE_OS_WINNT,	"UNIX"			},
90da6c28aaSamw 		{ NATIVE_OS_MACOS,	"MacOS" 		}
91da6c28aaSamw 	};
92da6c28aaSamw 
93da6c28aaSamw 	int i;
94da6c28aaSamw 	int len;
95*fc724630SAlan Wright 	const char *name;
96da6c28aaSamw 
97*fc724630SAlan Wright 	if (native_os == NULL)
98da6c28aaSamw 		return (NATIVE_OS_UNKNOWN);
99da6c28aaSamw 
10055bf511dSas200622 	/*
10155bf511dSas200622 	 * Windows Vista sends an empty native OS string.
10255bf511dSas200622 	 */
103*fc724630SAlan Wright 	if (*native_os == '\0')
10455bf511dSas200622 		return (NATIVE_OS_WIN2000);
10555bf511dSas200622 
106da6c28aaSamw 	for (i = 0; i < sizeof (os_table)/sizeof (os_table[0]); ++i) {
107*fc724630SAlan Wright 		name = os_table[i].sn_name;
108*fc724630SAlan Wright 		len = strlen(name);
109da6c28aaSamw 
110*fc724630SAlan Wright 		if (utf8_strncasecmp(name, native_os, len) == 0)
111*fc724630SAlan Wright 			return (os_table[i].sn_value);
112da6c28aaSamw 	}
113*fc724630SAlan Wright 
114da6c28aaSamw 	return (NATIVE_OS_UNKNOWN);
115da6c28aaSamw }
116da6c28aaSamw 
117da6c28aaSamw /*
118da6c28aaSamw  * smbnative_lm_value
119da6c28aaSamw  *
120da6c28aaSamw  * Return the appropriate native LanMan value for the specified native
121da6c28aaSamw  * LanMan name. There's an alignment problem in some packets from some
122da6c28aaSamw  * clients that means we can miss the first character, so we do an
123da6c28aaSamw  * additional check starting from the second character.
124da6c28aaSamw  *
125*fc724630SAlan Wright  * Example LanMan values:
126da6c28aaSamw  *
127*fc724630SAlan Wright  *	NT LAN Manager 4.0
128*fc724630SAlan Wright  *	Windows 4.0
129*fc724630SAlan Wright  *	Windows NT, Windows NT 4.0
130*fc724630SAlan Wright  *	Windows 2000 LAN Manager
131*fc724630SAlan Wright  *	Windows 2000, Windows 2000 5.0, Windows 2000 5.1
132*fc724630SAlan Wright  *	Windows 2002, Windows 2002 5.1
133*fc724630SAlan Wright  *	Windows .NET, Windows .NET 5.2
134*fc724630SAlan Wright  *	Windows Server 2003
135*fc724630SAlan Wright  *	Windows XP
136*fc724630SAlan Wright  *	NETSMB		(Solaris CIFS client)
137*fc724630SAlan Wright  *	DAVE		(Thursby Software: CIFS for MacOS)
138*fc724630SAlan Wright  *	Samba
139da6c28aaSamw  */
140da6c28aaSamw int
141*fc724630SAlan Wright smbnative_lm_value(const char *native_lm)
142da6c28aaSamw {
143*fc724630SAlan Wright 	static smb_native_t lm_table[] = {
144da6c28aaSamw 		{ NATIVE_LM_NT,		"NT LAN Manager 4.0"		},
145da6c28aaSamw 		{ NATIVE_LM_NT,		"Windows NT"			},
146da6c28aaSamw 		{ NATIVE_LM_NT,		"Windows 4.0"			},
147da6c28aaSamw 		{ NATIVE_LM_NT,		"DAVE"				}
148da6c28aaSamw 	};
149da6c28aaSamw 
150da6c28aaSamw 	int i;
151da6c28aaSamw 	int len;
152*fc724630SAlan Wright 	const char *name;
153da6c28aaSamw 
15455bf511dSas200622 	/*
15555bf511dSas200622 	 * Windows Vista sends an empty native LM string.
15655bf511dSas200622 	 */
157*fc724630SAlan Wright 	if (native_lm == NULL || *native_lm == '\0')
15855bf511dSas200622 		return (NATIVE_LM_WIN2000);
15955bf511dSas200622 
160da6c28aaSamw 	for (i = 0; i < sizeof (lm_table)/sizeof (lm_table[0]); ++i) {
161*fc724630SAlan Wright 		name = lm_table[i].sn_name;
162*fc724630SAlan Wright 		len = strlen(name);
163da6c28aaSamw 
164*fc724630SAlan Wright 		if ((utf8_strncasecmp(name, native_lm, len) == 0) ||
165*fc724630SAlan Wright 		    (utf8_strncasecmp(&name[1], native_lm, len - 1) == 0)) {
166*fc724630SAlan Wright 			return (lm_table[i].sn_value);
167da6c28aaSamw 		}
168da6c28aaSamw 	}
169*fc724630SAlan Wright 
170*fc724630SAlan Wright 	return (NATIVE_LM_WIN2000);
171da6c28aaSamw }
172da6c28aaSamw 
173da6c28aaSamw /*
174da6c28aaSamw  * smbnative_pdc_value
175da6c28aaSamw  *
176*fc724630SAlan Wright  * This function is called when libsmbrdr connects to a PDC.
177*fc724630SAlan Wright  * The PDC type is derived from the Native LanMan string.
178*fc724630SAlan Wright  * The PDC value will default to PDC_WIN2000.
179da6c28aaSamw  *
180*fc724630SAlan Wright  * Example strings:
181*fc724630SAlan Wright  *
182*fc724630SAlan Wright  *	NT LAN Manager 4.0
183*fc724630SAlan Wright  *	Windows 4.0, Windows NT, Windows NT 4.0
184*fc724630SAlan Wright  *	Windows 2000 LAN Manager
185*fc724630SAlan Wright  *	Windows 2000, Windows 2000 5.0, Windows 2000 5.1
186*fc724630SAlan Wright  *	Windows 2002, Windows 2002 5.1
187*fc724630SAlan Wright  *	Windows .NET, Windows .NET 5.2
188*fc724630SAlan Wright  *	Samba
189*fc724630SAlan Wright  *	DAVE
190da6c28aaSamw  */
191da6c28aaSamw int
192*fc724630SAlan Wright smbnative_pdc_value(const char *native_lm)
193da6c28aaSamw {
194*fc724630SAlan Wright 	static smb_native_t pdc_table[] = {
195da6c28aaSamw 		{ PDC_WINNT,	"NT LAN Manager 4.0"		},
196da6c28aaSamw 		{ PDC_WINNT,	"Windows NT 4.0"		},
197da6c28aaSamw 		{ PDC_WINNT,	"Windows NT"			},
198da6c28aaSamw 		{ PDC_WINNT,	"Windows 4.0"			},
199*fc724630SAlan Wright 		{ PDC_WINNT,	"DAVE"				},
200*fc724630SAlan Wright 		{ PDC_SAMBA,	"Samba"				}
201da6c28aaSamw 	};
202da6c28aaSamw 
203da6c28aaSamw 	int i;
204da6c28aaSamw 	int len;
205*fc724630SAlan Wright 	const char *name;
206da6c28aaSamw 
207*fc724630SAlan Wright 	if (native_lm == NULL || *native_lm == '\0')
208*fc724630SAlan Wright 		return (PDC_WIN2000);
209da6c28aaSamw 
210da6c28aaSamw 	for (i = 0; i < sizeof (pdc_table)/sizeof (pdc_table[0]); ++i) {
211*fc724630SAlan Wright 		name = pdc_table[i].sn_name;
212*fc724630SAlan Wright 		len = strlen(name);
213da6c28aaSamw 
214*fc724630SAlan Wright 		if ((utf8_strncasecmp(name, native_lm, len) == 0) ||
215*fc724630SAlan Wright 		    (utf8_strncasecmp(&name[1], native_lm, len - 1) == 0)) {
216*fc724630SAlan Wright 			return (pdc_table[i].sn_value);
217da6c28aaSamw 		}
218da6c28aaSamw 	}
219da6c28aaSamw 
220*fc724630SAlan Wright 	return (PDC_WIN2000);
221da6c28aaSamw }
222