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