xref: /titanic_41/usr/src/common/smbsrv/smb_native.c (revision 55bf511df53aad0fdb7eb3fa349f0308cc05234c)
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 /*
22da6c28aaSamw  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23da6c28aaSamw  * Use is subject to license terms.
24da6c28aaSamw  */
25da6c28aaSamw 
26da6c28aaSamw #pragma ident	"%Z%%M%	%I%	%E% SMI"
27da6c28aaSamw 
28da6c28aaSamw /*
29da6c28aaSamw  * This module defines generic functions to map Native OS and Native
30da6c28aaSamw  * LanMan names to values.
31da6c28aaSamw  */
32da6c28aaSamw 
33da6c28aaSamw #ifdef _KERNEL
34da6c28aaSamw #include <sys/types.h>
35da6c28aaSamw #include <sys/sunddi.h>
36da6c28aaSamw #else
37da6c28aaSamw #include <string.h>
38da6c28aaSamw #endif
39da6c28aaSamw #include <smbsrv/string.h>
40da6c28aaSamw #include <smbsrv/smbinfo.h>
41da6c28aaSamw 
42da6c28aaSamw /*
43da6c28aaSamw  * smbnative_os_value
44da6c28aaSamw  *
45da6c28aaSamw  * Return the appropriate native OS value for the specified native OS name.
46da6c28aaSamw  *
47da6c28aaSamw  * Windows 2000 server:            "Windows 2000 2195"
48da6c28aaSamw  * Windows XP Professional client: "Windows 2002 2543"
49da6c28aaSamw  * Windows XP PDC server:          "Windows 5.1"
50da6c28aaSamw  * Windows .Net:                   "Windows .NET 3621"
51da6c28aaSamw  * Windows .Net:                   "Windows .NET 3718"
52da6c28aaSamw  *
53da6c28aaSamw  * DAVE (Thursby Software: CIFS for MacOS) uses "MacOS", sometimes with a
54da6c28aaSamw  * version number appended, i.e. "MacOS 8.5.1". We treat DAVE like NT 4.0
55da6c28aaSamw  * except for the cases that DAVE clients set 'watch tree' flag in notify
56da6c28aaSamw  * change requests.
57da6c28aaSamw  *
58da6c28aaSamw  * Samba reports UNIX as its Native OS, which we can map to NT 4.0.
59da6c28aaSamw  */
60da6c28aaSamw int
61da6c28aaSamw smbnative_os_value(char *native_os)
62da6c28aaSamw {
63da6c28aaSamw 	typedef struct native_os_table {
64da6c28aaSamw 		int os_value;
65da6c28aaSamw 		char *os_name;
66da6c28aaSamw 	} native_os_table_t;
67da6c28aaSamw 
68da6c28aaSamw 	static native_os_table_t os_table[] = {
69da6c28aaSamw 		{ NATIVE_OS_WINNT,	"Windows NT 4.0"	},
70da6c28aaSamw 		{ NATIVE_OS_WINNT,	"Windows NT"		},
71da6c28aaSamw 		{ NATIVE_OS_WIN95,	"Windows 4.0"		},
72da6c28aaSamw 		{ NATIVE_OS_WIN2000,	"Windows 5.0"		},
73da6c28aaSamw 		{ NATIVE_OS_WIN2000,	"Windows 5.1"		},
74da6c28aaSamw 		{ NATIVE_OS_WIN2000,	"Windows 2000 5.0"	},
75da6c28aaSamw 		{ NATIVE_OS_NT5_1,	"Windows 2000 5.1"	},
76da6c28aaSamw 		{ NATIVE_OS_WIN2000,	"Windows 2000"		},
77da6c28aaSamw 		{ NATIVE_OS_WIN2000,	"Windows 2002"		},
78da6c28aaSamw 		{ NATIVE_OS_WIN2000,	"Windows .NET"		},
79da6c28aaSamw 		{ NATIVE_OS_WIN2000,	"Windows Server 2003"	},
80da6c28aaSamw 		{ NATIVE_OS_WIN2000,	"Windows XP"		},
81da6c28aaSamw 		{ NATIVE_OS_WINNT,	"UNIX"			},
82da6c28aaSamw 		{ NATIVE_OS_MACOS,	"MacOS" 		}
83da6c28aaSamw 	};
84da6c28aaSamw 
85da6c28aaSamw 	int i;
86da6c28aaSamw 	int len;
87da6c28aaSamw 	char *os_name;
88da6c28aaSamw 
89da6c28aaSamw 	if (native_os == NULL) {
90da6c28aaSamw 		return (NATIVE_OS_UNKNOWN);
91da6c28aaSamw 	}
92da6c28aaSamw 
93*55bf511dSas200622 	if (*native_os == '\0') {
94*55bf511dSas200622 		/*
95*55bf511dSas200622 		 * Windows Vista sends an empty native OS string.
96*55bf511dSas200622 		 */
97*55bf511dSas200622 		return (NATIVE_OS_WIN2000);
98*55bf511dSas200622 	}
99*55bf511dSas200622 
100da6c28aaSamw 	for (i = 0; i < sizeof (os_table)/sizeof (os_table[0]); ++i) {
101da6c28aaSamw 		os_name = os_table[i].os_name;
102da6c28aaSamw 		len = strlen(os_name);
103da6c28aaSamw 
104da6c28aaSamw 		if (utf8_strncasecmp(os_name, native_os, len) == 0) {
105da6c28aaSamw 			return (os_table[i].os_value);
106da6c28aaSamw 		}
107da6c28aaSamw 	}
108da6c28aaSamw 	return (NATIVE_OS_UNKNOWN);
109da6c28aaSamw }
110da6c28aaSamw 
111da6c28aaSamw 
112da6c28aaSamw /*
113da6c28aaSamw  * smbnative_lm_value
114da6c28aaSamw  *
115da6c28aaSamw  * Return the appropriate native LanMan value for the specified native
116da6c28aaSamw  * LanMan name. There's an alignment problem in some packets from some
117da6c28aaSamw  * clients that means we can miss the first character, so we do an
118da6c28aaSamw  * additional check starting from the second character.
119da6c28aaSamw  *
120da6c28aaSamw  * DAVE (Thursby Software: CIFS for MacOS) sometimes uses a Unicode
121da6c28aaSamw  * character in the LanMan name. Variations seen so far are:
122da6c28aaSamw  *
123da6c28aaSamw  *	44 00 41 00 56 00 45 00 00 00        D.A.V.E...
124da6c28aaSamw  *
125da6c28aaSamw  *	44 00 41 00 56 00 45 00 22 21 20 00 56 00 32 00
126da6c28aaSamw  *	2E 00 35 00 2E 00 31 00 00 00        D.A.V.E."!..V.2...5...1...
127da6c28aaSamw  *
128da6c28aaSamw  * Samba reports its own name (Samba) as its Native LM, which we can
129da6c28aaSamw  * map to NT LM 4.0.
130da6c28aaSamw  */
131da6c28aaSamw int
132da6c28aaSamw smbnative_lm_value(char *native_lm)
133da6c28aaSamw {
134da6c28aaSamw 	typedef struct native_lm_table {
135da6c28aaSamw 		int lm_value;
136da6c28aaSamw 		char *lm_name;
137da6c28aaSamw 	} native_lm_table_t;
138da6c28aaSamw 
139da6c28aaSamw 	static native_lm_table_t lm_table[] = {
140da6c28aaSamw 		{ NATIVE_LM_NT,		"NT LAN Manager 4.0"		},
141da6c28aaSamw 		{ NATIVE_LM_NT,		"Windows NT 4.0"		},
142da6c28aaSamw 		{ NATIVE_LM_NT,		"Windows NT"			},
143da6c28aaSamw 		{ NATIVE_LM_NT,		"Windows 4.0"			},
144da6c28aaSamw 		{ NATIVE_LM_WIN2000,	"Windows 2000 LAN Manager"	},
145da6c28aaSamw 		{ NATIVE_LM_WIN2000,	"Windows 2000 5.0"		},
146da6c28aaSamw 		{ NATIVE_LM_WIN2000,	"Windows 2000 5.1"		},
147da6c28aaSamw 		{ NATIVE_LM_WIN2000,	"Windows 2000",			},
148da6c28aaSamw 		{ NATIVE_LM_WIN2000,	"Windows 2002 5.1"		},
149da6c28aaSamw 		{ NATIVE_LM_WIN2000,	"Windows 2002"			},
150da6c28aaSamw 		{ NATIVE_LM_WIN2000,	"Windows .NET 5.2"		},
151da6c28aaSamw 		{ NATIVE_LM_WIN2000,	"Windows .NET"			},
152da6c28aaSamw 		{ NATIVE_LM_WIN2000,	"Windows Server 2003"		},
153da6c28aaSamw 		{ NATIVE_LM_WIN2000,	"Windows XP"			},
154da6c28aaSamw 		{ NATIVE_LM_NT,		"Samba"				},
155da6c28aaSamw 		{ NATIVE_LM_NT,		"DAVE"				}
156da6c28aaSamw 	};
157da6c28aaSamw 
158da6c28aaSamw 	int i;
159da6c28aaSamw 	int len;
160da6c28aaSamw 	char *lm_name;
161da6c28aaSamw 
162da6c28aaSamw 	if (native_lm == NULL) {
163da6c28aaSamw 		return (NATIVE_LM_NONE);
164da6c28aaSamw 	}
165da6c28aaSamw 
166*55bf511dSas200622 	if (*native_lm == '\0') {
167*55bf511dSas200622 		/*
168*55bf511dSas200622 		 * Windows Vista sends an empty native LM string.
169*55bf511dSas200622 		 */
170*55bf511dSas200622 		return (NATIVE_LM_WIN2000);
171*55bf511dSas200622 	}
172*55bf511dSas200622 
173da6c28aaSamw 	for (i = 0; i < sizeof (lm_table)/sizeof (lm_table[0]); ++i) {
174da6c28aaSamw 		lm_name = lm_table[i].lm_name;
175da6c28aaSamw 		len = strlen(lm_name);
176da6c28aaSamw 
177da6c28aaSamw 		if ((utf8_strncasecmp(lm_name, native_lm, len) == 0) ||
178da6c28aaSamw 		    (utf8_strncasecmp(&lm_name[1], native_lm, len - 1) == 0)) {
179da6c28aaSamw 			return (lm_table[i].lm_value);
180da6c28aaSamw 		}
181da6c28aaSamw 	}
182da6c28aaSamw 	return (NATIVE_LM_NONE);
183da6c28aaSamw }
184da6c28aaSamw 
185da6c28aaSamw /*
186da6c28aaSamw  * smbnative_pdc_value
187da6c28aaSamw  *
188da6c28aaSamw  * This function is used when NetFORCE contacting a PDC
189da6c28aaSamw  * to authenticate a connected user to determine and keep
190da6c28aaSamw  * the PDC type.
191da6c28aaSamw  *
192da6c28aaSamw  * The reason for adding this functionality is that NetFORCE
193da6c28aaSamw  * doesn't support Samba PDC but code didn't check the PDC type
194da6c28aaSamw  * and do authentication agains any PDC. This behaviour could
195da6c28aaSamw  * cause problem in some circumstances.
196da6c28aaSamw  * Now that we determine the PDC type the authentication code
197da6c28aaSamw  * can be configured (by smb.samba.pdc env var) to return access
198da6c28aaSamw  * denied to authentication attempts when PDC is Samba.
199da6c28aaSamw  */
200da6c28aaSamw int
201da6c28aaSamw smbnative_pdc_value(char *native_lm)
202da6c28aaSamw {
203da6c28aaSamw 	typedef struct pdc_table {
204da6c28aaSamw 		int pdc_value;
205da6c28aaSamw 		char *pdc_lmname;
206da6c28aaSamw 	} pdc_table_t;
207da6c28aaSamw 
208da6c28aaSamw 	static pdc_table_t pdc_table[] = {
209da6c28aaSamw 		{ PDC_WINNT,	"NT LAN Manager 4.0"		},
210da6c28aaSamw 		{ PDC_WINNT,	"Windows NT 4.0"		},
211da6c28aaSamw 		{ PDC_WINNT,	"Windows NT"			},
212da6c28aaSamw 		{ PDC_WINNT,	"Windows 4.0"			},
213da6c28aaSamw 		{ PDC_WIN2000,	"Windows 2000 LAN Manager"	},
214da6c28aaSamw 		{ PDC_WIN2000,	"Windows 2000 5.0"		},
215da6c28aaSamw 		{ PDC_WIN2000,	"Windows 2000 5.1"		},
216da6c28aaSamw 		{ PDC_WIN2000,	"Windows 2000",			},
217da6c28aaSamw 		{ PDC_WIN2000,	"Windows 2002 5.1"		},
218da6c28aaSamw 		{ PDC_WIN2000,	"Windows 2002"			},
219da6c28aaSamw 		{ PDC_WIN2000,	"Windows .NET 5.2"		},
220da6c28aaSamw 		{ PDC_WIN2000,	"Windows .NET"			},
221da6c28aaSamw 		{ PDC_SAMBA,	"Samba"				},
222da6c28aaSamw 		{ PDC_WINNT,	"DAVE"				}
223da6c28aaSamw 	};
224da6c28aaSamw 
225da6c28aaSamw 	int i;
226da6c28aaSamw 	int len;
227da6c28aaSamw 	char *pdc_lmname;
228da6c28aaSamw 
229da6c28aaSamw 	if (native_lm == 0) {
230da6c28aaSamw 		return (PDC_UNKNOWN);
231da6c28aaSamw 	}
232da6c28aaSamw 
233da6c28aaSamw 	for (i = 0; i < sizeof (pdc_table)/sizeof (pdc_table[0]); ++i) {
234da6c28aaSamw 		pdc_lmname = pdc_table[i].pdc_lmname;
235da6c28aaSamw 		len = strlen(pdc_lmname);
236da6c28aaSamw 
237da6c28aaSamw 		if ((utf8_strncasecmp(pdc_lmname, native_lm, len) == 0) ||
238da6c28aaSamw 		    (utf8_strncasecmp(&pdc_lmname[1], native_lm, len - 1)
239da6c28aaSamw 		    == 0)) {
240da6c28aaSamw 			return (pdc_table[i].pdc_value);
241da6c28aaSamw 		}
242da6c28aaSamw 	}
243da6c28aaSamw 
244da6c28aaSamw 	return (PDC_UNKNOWN);
245da6c28aaSamw }
246