15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw /*
22*9021Samw@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
235331Samw  * Use is subject to license terms.
245331Samw  */
255331Samw 
265331Samw /*
275331Samw  * This module defines generic functions to map Native OS and Native
285331Samw  * LanMan names to values.
295331Samw  */
305331Samw 
315331Samw #ifdef _KERNEL
325331Samw #include <sys/types.h>
335331Samw #include <sys/sunddi.h>
345331Samw #else
355331Samw #include <string.h>
365331Samw #endif
375331Samw #include <smbsrv/string.h>
385331Samw #include <smbsrv/smbinfo.h>
395331Samw 
40*9021Samw@Sun.COM typedef struct smb_native {
41*9021Samw@Sun.COM 	int sn_value;
42*9021Samw@Sun.COM 	const char *sn_name;
43*9021Samw@Sun.COM } smb_native_t;
44*9021Samw@Sun.COM 
455331Samw /*
465331Samw  * smbnative_os_value
475331Samw  *
485331Samw  * Return the appropriate native OS value for the specified native OS name.
495331Samw  *
50*9021Samw@Sun.COM  * Example OS values used by Windows:
51*9021Samw@Sun.COM  *
52*9021Samw@Sun.COM  *	Windows 4.0, Windows NT, Windows NT 4.0
53*9021Samw@Sun.COM  *	Windows 5.0, Windows 5.1
54*9021Samw@Sun.COM  *	Windows 2000, Windows 2000 5.0, Windows 2000 5.1
55*9021Samw@Sun.COM  *	Windows 2002
56*9021Samw@Sun.COM  *	Windows .NET
57*9021Samw@Sun.COM  *	Windows Server 2003
58*9021Samw@Sun.COM  *	Windows XP
59*9021Samw@Sun.COM  *
605331Samw  * Windows 2000 server:            "Windows 2000 2195"
615331Samw  * Windows XP Professional client: "Windows 2002 2543"
625331Samw  * Windows XP PDC server:          "Windows 5.1"
635331Samw  * Windows .Net:                   "Windows .NET 3621"
645331Samw  * Windows .Net:                   "Windows .NET 3718"
655331Samw  *
665331Samw  * DAVE (Thursby Software: CIFS for MacOS) uses "MacOS", sometimes with a
675331Samw  * version number appended, i.e. "MacOS 8.5.1". We treat DAVE like NT 4.0
685331Samw  * except for the cases that DAVE clients set 'watch tree' flag in notify
695331Samw  * change requests.
705331Samw  *
715331Samw  * Samba reports UNIX as its Native OS, which we can map to NT 4.0.
725331Samw  */
735331Samw int
74*9021Samw@Sun.COM smbnative_os_value(const char *native_os)
755331Samw {
76*9021Samw@Sun.COM 	static smb_native_t os_table[] = {
775331Samw 		{ NATIVE_OS_WINNT,	"Windows NT 4.0"	},
785331Samw 		{ NATIVE_OS_WINNT,	"Windows NT"		},
795331Samw 		{ NATIVE_OS_WIN95,	"Windows 4.0"		},
805331Samw 		{ NATIVE_OS_WIN2000,	"Windows 5.0"		},
815331Samw 		{ NATIVE_OS_WIN2000,	"Windows 5.1"		},
825331Samw 		{ NATIVE_OS_WIN2000,	"Windows 2000 5.0"	},
835331Samw 		{ NATIVE_OS_NT5_1,	"Windows 2000 5.1"	},
845331Samw 		{ NATIVE_OS_WIN2000,	"Windows 2000"		},
855331Samw 		{ NATIVE_OS_WIN2000,	"Windows 2002"		},
865331Samw 		{ NATIVE_OS_WIN2000,	"Windows .NET"		},
87*9021Samw@Sun.COM 		{ NATIVE_OS_WIN2000,	"Windows Server"	},
885331Samw 		{ NATIVE_OS_WIN2000,	"Windows XP"		},
895331Samw 		{ NATIVE_OS_WINNT,	"UNIX"			},
905331Samw 		{ NATIVE_OS_MACOS,	"MacOS" 		}
915331Samw 	};
925331Samw 
935331Samw 	int i;
945331Samw 	int len;
95*9021Samw@Sun.COM 	const char *name;
96*9021Samw@Sun.COM 
97*9021Samw@Sun.COM 	if (native_os == NULL)
98*9021Samw@Sun.COM 		return (NATIVE_OS_UNKNOWN);
995331Samw 
100*9021Samw@Sun.COM 	/*
101*9021Samw@Sun.COM 	 * Windows Vista sends an empty native OS string.
102*9021Samw@Sun.COM 	 */
103*9021Samw@Sun.COM 	if (*native_os == '\0')
104*9021Samw@Sun.COM 		return (NATIVE_OS_WIN2000);
105*9021Samw@Sun.COM 
106*9021Samw@Sun.COM 	for (i = 0; i < sizeof (os_table)/sizeof (os_table[0]); ++i) {
107*9021Samw@Sun.COM 		name = os_table[i].sn_name;
108*9021Samw@Sun.COM 		len = strlen(name);
109*9021Samw@Sun.COM 
110*9021Samw@Sun.COM 		if (utf8_strncasecmp(name, native_os, len) == 0)
111*9021Samw@Sun.COM 			return (os_table[i].sn_value);
1125331Samw 	}
1135331Samw 
1145331Samw 	return (NATIVE_OS_UNKNOWN);
1155331Samw }
1165331Samw 
1175331Samw /*
1185331Samw  * smbnative_lm_value
1195331Samw  *
1205331Samw  * Return the appropriate native LanMan value for the specified native
1215331Samw  * LanMan name. There's an alignment problem in some packets from some
1225331Samw  * clients that means we can miss the first character, so we do an
1235331Samw  * additional check starting from the second character.
1245331Samw  *
125*9021Samw@Sun.COM  * Example LanMan values:
1265331Samw  *
127*9021Samw@Sun.COM  *	NT LAN Manager 4.0
128*9021Samw@Sun.COM  *	Windows 4.0
129*9021Samw@Sun.COM  *	Windows NT, Windows NT 4.0
130*9021Samw@Sun.COM  *	Windows 2000 LAN Manager
131*9021Samw@Sun.COM  *	Windows 2000, Windows 2000 5.0, Windows 2000 5.1
132*9021Samw@Sun.COM  *	Windows 2002, Windows 2002 5.1
133*9021Samw@Sun.COM  *	Windows .NET, Windows .NET 5.2
134*9021Samw@Sun.COM  *	Windows Server 2003
135*9021Samw@Sun.COM  *	Windows XP
136*9021Samw@Sun.COM  *	NETSMB		(Solaris CIFS client)
137*9021Samw@Sun.COM  *	DAVE		(Thursby Software: CIFS for MacOS)
138*9021Samw@Sun.COM  *	Samba
1395331Samw  */
1405331Samw int
141*9021Samw@Sun.COM smbnative_lm_value(const char *native_lm)
1425331Samw {
143*9021Samw@Sun.COM 	static smb_native_t lm_table[] = {
1445331Samw 		{ NATIVE_LM_NT,		"NT LAN Manager 4.0"		},
1455331Samw 		{ NATIVE_LM_NT,		"Windows NT"			},
1465331Samw 		{ NATIVE_LM_NT,		"Windows 4.0"			},
1475331Samw 		{ NATIVE_LM_NT,		"DAVE"				}
1485331Samw 	};
1495331Samw 
1505331Samw 	int i;
1515331Samw 	int len;
152*9021Samw@Sun.COM 	const char *name;
153*9021Samw@Sun.COM 
154*9021Samw@Sun.COM 	/*
155*9021Samw@Sun.COM 	 * Windows Vista sends an empty native LM string.
156*9021Samw@Sun.COM 	 */
157*9021Samw@Sun.COM 	if (native_lm == NULL || *native_lm == '\0')
158*9021Samw@Sun.COM 		return (NATIVE_LM_WIN2000);
1595331Samw 
160*9021Samw@Sun.COM 	for (i = 0; i < sizeof (lm_table)/sizeof (lm_table[0]); ++i) {
161*9021Samw@Sun.COM 		name = lm_table[i].sn_name;
162*9021Samw@Sun.COM 		len = strlen(name);
163*9021Samw@Sun.COM 
164*9021Samw@Sun.COM 		if ((utf8_strncasecmp(name, native_lm, len) == 0) ||
165*9021Samw@Sun.COM 		    (utf8_strncasecmp(&name[1], native_lm, len - 1) == 0)) {
166*9021Samw@Sun.COM 			return (lm_table[i].sn_value);
167*9021Samw@Sun.COM 		}
1685331Samw 	}
1695331Samw 
170*9021Samw@Sun.COM 	return (NATIVE_LM_WIN2000);
1715331Samw }
1725331Samw 
1735331Samw /*
1745331Samw  * smbnative_pdc_value
1755331Samw  *
176*9021Samw@Sun.COM  * This function is called when libsmbrdr connects to a PDC.
177*9021Samw@Sun.COM  * The PDC type is derived from the Native LanMan string.
178*9021Samw@Sun.COM  * The PDC value will default to PDC_WIN2000.
179*9021Samw@Sun.COM  *
180*9021Samw@Sun.COM  * Example strings:
1815331Samw  *
182*9021Samw@Sun.COM  *	NT LAN Manager 4.0
183*9021Samw@Sun.COM  *	Windows 4.0, Windows NT, Windows NT 4.0
184*9021Samw@Sun.COM  *	Windows 2000 LAN Manager
185*9021Samw@Sun.COM  *	Windows 2000, Windows 2000 5.0, Windows 2000 5.1
186*9021Samw@Sun.COM  *	Windows 2002, Windows 2002 5.1
187*9021Samw@Sun.COM  *	Windows .NET, Windows .NET 5.2
188*9021Samw@Sun.COM  *	Samba
189*9021Samw@Sun.COM  *	DAVE
1905331Samw  */
1915331Samw int
192*9021Samw@Sun.COM smbnative_pdc_value(const char *native_lm)
1935331Samw {
194*9021Samw@Sun.COM 	static smb_native_t pdc_table[] = {
1955331Samw 		{ PDC_WINNT,	"NT LAN Manager 4.0"		},
1965331Samw 		{ PDC_WINNT,	"Windows NT 4.0"		},
1975331Samw 		{ PDC_WINNT,	"Windows NT"			},
1985331Samw 		{ PDC_WINNT,	"Windows 4.0"			},
199*9021Samw@Sun.COM 		{ PDC_WINNT,	"DAVE"				},
200*9021Samw@Sun.COM 		{ PDC_SAMBA,	"Samba"				}
2015331Samw 	};
2025331Samw 
2035331Samw 	int i;
2045331Samw 	int len;
205*9021Samw@Sun.COM 	const char *name;
2065331Samw 
207*9021Samw@Sun.COM 	if (native_lm == NULL || *native_lm == '\0')
208*9021Samw@Sun.COM 		return (PDC_WIN2000);
2095331Samw 
2105331Samw 	for (i = 0; i < sizeof (pdc_table)/sizeof (pdc_table[0]); ++i) {
211*9021Samw@Sun.COM 		name = pdc_table[i].sn_name;
212*9021Samw@Sun.COM 		len = strlen(name);
2135331Samw 
214*9021Samw@Sun.COM 		if ((utf8_strncasecmp(name, native_lm, len) == 0) ||
215*9021Samw@Sun.COM 		    (utf8_strncasecmp(&name[1], native_lm, len - 1) == 0)) {
216*9021Samw@Sun.COM 			return (pdc_table[i].sn_value);
2175331Samw 		}
2185331Samw 	}
2195331Samw 
220*9021Samw@Sun.COM 	return (PDC_WIN2000);
2215331Samw }
222