This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.(This used to...
[ira/wip.git] / source3 / smbd / negprot.c
1 /* 
2    Unix SMB/CIFS implementation.
3    negprot reply code
4    Copyright (C) Andrew Tridgell 1992-1998
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 extern int Protocol;
24 extern int max_recv;
25 extern fstring global_myworkgroup;
26 extern fstring remote_machine;
27 BOOL global_encrypted_passwords_negotiated = False;
28 BOOL global_spnego_negotiated = False;
29 struct auth_context *negprot_global_auth_context = NULL;
30
31 static void get_challenge(char buff[8]) 
32 {
33         NTSTATUS nt_status;
34         const uint8 *cryptkey;
35
36         /* We might be called more than once, muliple negprots are premitted */
37         if (negprot_global_auth_context) {
38                 DEBUG(3, ("get challenge: is this a secondary negprot?  negprot_global_auth_context is non-NULL!\n"));
39                 (negprot_global_auth_context->free)(&negprot_global_auth_context);
40         }
41
42         DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
43         if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) {
44                 DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status)));
45                 smb_panic("cannot make_negprot_global_auth_context!\n");
46         }
47         DEBUG(10, ("get challenge: getting challenge\n"));
48         cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context);
49         memcpy(buff, cryptkey, 8);
50 }
51
52 /****************************************************************************
53 reply for the core protocol
54 ****************************************************************************/
55 static int reply_corep(char *inbuf, char *outbuf)
56 {
57         int outsize = set_message(outbuf,1,0,True);
58
59         Protocol = PROTOCOL_CORE;
60         
61         return outsize;
62 }
63
64
65 /****************************************************************************
66 reply for the coreplus protocol
67 ****************************************************************************/
68 static int reply_coreplus(char *inbuf, char *outbuf)
69 {
70   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
71   int outsize = set_message(outbuf,13,0,True);
72   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
73                                  readbraw and writebraw (possibly) */
74   /* Reply, SMBlockread, SMBwritelock supported. */
75   SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
76   SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */  
77
78   Protocol = PROTOCOL_COREPLUS;
79
80   return outsize;
81 }
82
83
84 /****************************************************************************
85 reply for the lanman 1.0 protocol
86 ****************************************************************************/
87 static int reply_lanman1(char *inbuf, char *outbuf)
88 {
89   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
90   int secword=0;
91   time_t t = time(NULL);
92
93   global_encrypted_passwords_negotiated = lp_encrypted_passwords();
94
95   if (lp_security()>=SEC_USER) secword |= 1;
96   if (global_encrypted_passwords_negotiated) secword |= 2;
97
98   set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
99   SSVAL(outbuf,smb_vwv1,secword); 
100   /* Create a token value and add it to the outgoing packet. */
101   if (global_encrypted_passwords_negotiated) {
102           get_challenge(smb_buf(outbuf));
103   }
104
105   Protocol = PROTOCOL_LANMAN1;
106
107   /* Reply, SMBlockread, SMBwritelock supported. */
108   SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
109   SSVAL(outbuf,smb_vwv2,max_recv);
110   SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
111   SSVAL(outbuf,smb_vwv4,1);
112   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
113                                  readbraw writebraw (possibly) */
114   SIVAL(outbuf,smb_vwv6,sys_getpid());
115   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
116
117   put_dos_date(outbuf,smb_vwv8,t);
118
119   return (smb_len(outbuf)+4);
120 }
121
122
123 /****************************************************************************
124 reply for the lanman 2.0 protocol
125 ****************************************************************************/
126 static int reply_lanman2(char *inbuf, char *outbuf)
127 {
128   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
129   int secword=0;
130   time_t t = time(NULL);
131
132   global_encrypted_passwords_negotiated = lp_encrypted_passwords();
133   
134   if (lp_security()>=SEC_USER) secword |= 1;
135   if (global_encrypted_passwords_negotiated) secword |= 2;
136
137   set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
138   SSVAL(outbuf,smb_vwv1,secword); 
139   SIVAL(outbuf,smb_vwv6,sys_getpid());
140
141   /* Create a token value and add it to the outgoing packet. */
142   if (global_encrypted_passwords_negotiated) {
143           get_challenge(smb_buf(outbuf));
144   }
145
146   Protocol = PROTOCOL_LANMAN2;
147
148   /* Reply, SMBlockread, SMBwritelock supported. */
149   SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
150   SSVAL(outbuf,smb_vwv2,max_recv);
151   SSVAL(outbuf,smb_vwv3,lp_maxmux()); 
152   SSVAL(outbuf,smb_vwv4,1);
153   SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
154   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
155   put_dos_date(outbuf,smb_vwv8,t);
156
157   return (smb_len(outbuf)+4);
158 }
159
160
161
162 /* 
163    generate the spnego negprot reply blob. Return the number of bytes used
164 */
165 static int negprot_spnego(char *p)
166 {
167         DATA_BLOB blob;
168         extern pstring global_myname;
169         uint8 guid[16];
170         const char *OIDs_krb5[] = {OID_NTLMSSP,
171                                    OID_KERBEROS5,
172                                    OID_KERBEROS5_OLD,
173                                    NULL};
174         const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
175         char *principal;
176         int len;
177
178         global_spnego_negotiated = True;
179
180         memset(guid, 0, 16);
181         safe_strcpy((char *)guid, global_myname, 16);
182         strlower((char *)guid);
183
184 #if 0
185         /* strangely enough, NT does not sent the single OID NTLMSSP when
186            not a ADS member, it sends no OIDs at all
187
188            we can't do this until we teach our sesssion setup parser to know
189            about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)
190         */
191         if (lp_security() != SEC_ADS) {
192                 memcpy(p, guid, 16);
193                 return 16;
194         }
195 #endif
196         if (lp_security() != SEC_ADS) {
197                 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
198         } else {
199                 ADS_STRUCT *ads;
200                 ads = ads_init(NULL, NULL, NULL, NULL);
201                 /* win2000 uses host$@REALM, which we will probably use eventually,
202                    but for now this works */
203                 asprintf(&principal, "HOST/%s@%s", guid, ads->realm);
204                 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
205                 free(principal);
206                 ads_destroy(&ads);
207         }
208         memcpy(p, blob.data, blob.length);
209         len = blob.length;
210         data_blob_free(&blob);
211         return len;
212 }
213
214                 
215
216 /****************************************************************************
217 reply for the nt protocol
218 ****************************************************************************/
219 static int reply_nt1(char *inbuf, char *outbuf)
220 {
221         /* dual names + lock_and_read + nt SMBs + remote API calls */
222         int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
223                 CAP_LEVEL_II_OPLOCKS;
224
225         int secword=0;
226         time_t t = time(NULL);
227         char *p, *q;
228         BOOL negotiate_spnego = False;
229
230         global_encrypted_passwords_negotiated = lp_encrypted_passwords();
231
232         /* do spnego in user level security if the client
233            supports it and we can do encrypted passwords */
234         
235         if (global_encrypted_passwords_negotiated && 
236             (lp_security() != SEC_SHARE) &&
237             lp_use_spnego() &&
238             (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
239                 negotiate_spnego = True;
240                 capabilities |= CAP_EXTENDED_SECURITY;
241         }
242         
243         capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNIX;
244         
245         if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
246                 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
247         
248         if (SMB_OFF_T_BITS == 64)
249                 capabilities |= CAP_LARGE_FILES;
250
251         if (lp_readraw() && lp_writeraw())
252                 capabilities |= CAP_RAW_MODE;
253         
254         /* allow for disabling unicode */
255         if (lp_unicode())
256                 capabilities |= CAP_UNICODE;
257
258         if (lp_nt_status_support())
259                 capabilities |= CAP_STATUS32;
260         
261         if (lp_host_msdfs())
262                 capabilities |= CAP_DFS;
263         
264         if (lp_security() >= SEC_USER)
265                 secword |= 1;
266         if (global_encrypted_passwords_negotiated)
267                 secword |= 2;
268         
269         set_message(outbuf,17,0,True);
270         
271         SCVAL(outbuf,smb_vwv1,secword);
272         
273         Protocol = PROTOCOL_NT1;
274         
275         SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
276         SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
277         SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
278         SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
279         SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
280         SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
281         put_long_date(outbuf+smb_vwv11+1,t);
282         SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
283         
284         p = q = smb_buf(outbuf);
285         if (!negotiate_spnego) {
286                 /* Create a token value and add it to the outgoing packet. */
287                 if (global_encrypted_passwords_negotiated) {
288                         get_challenge(p);
289                 }
290                 SSVALS(outbuf,smb_vwv16+1,8);
291                 p += 8;
292                 p += srvstr_push(outbuf, p, global_myworkgroup, -1, 
293                                  STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
294                 DEBUG(3,("not using SPNEGO\n"));
295         } else {
296                 int len = negprot_spnego(p);
297                 
298                 SSVALS(outbuf,smb_vwv16+1,len);
299                 p += len;
300                 DEBUG(3,("using SPNEGO\n"));
301         }
302         
303         SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
304         set_message_end(outbuf, p);
305         
306         return (smb_len(outbuf)+4);
307 }
308
309 /* these are the protocol lists used for auto architecture detection:
310
311 WinNT 3.51:
312 protocol [PC NETWORK PROGRAM 1.0]
313 protocol [XENIX CORE]
314 protocol [MICROSOFT NETWORKS 1.03]
315 protocol [LANMAN1.0]
316 protocol [Windows for Workgroups 3.1a]
317 protocol [LM1.2X002]
318 protocol [LANMAN2.1]
319 protocol [NT LM 0.12]
320
321 Win95:
322 protocol [PC NETWORK PROGRAM 1.0]
323 protocol [XENIX CORE]
324 protocol [MICROSOFT NETWORKS 1.03]
325 protocol [LANMAN1.0]
326 protocol [Windows for Workgroups 3.1a]
327 protocol [LM1.2X002]
328 protocol [LANMAN2.1]
329 protocol [NT LM 0.12]
330
331 Win2K:
332 protocol [PC NETWORK PROGRAM 1.0]
333 protocol [LANMAN1.0]
334 protocol [Windows for Workgroups 3.1a]
335 protocol [LM1.2X002]
336 protocol [LANMAN2.1]
337 protocol [NT LM 0.12]
338
339 OS/2:
340 protocol [PC NETWORK PROGRAM 1.0]
341 protocol [XENIX CORE]
342 protocol [LANMAN1.0]
343 protocol [LM1.2X002]
344 protocol [LANMAN2.1]
345 */
346
347 /*
348   * Modified to recognize the architecture of the remote machine better.
349   *
350   * This appears to be the matrix of which protocol is used by which
351   * MS product.
352        Protocol                       WfWg    Win95   WinNT  Win2K  OS/2
353        PC NETWORK PROGRAM 1.0          1       1       1      1      1
354        XENIX CORE                                      2             2
355        MICROSOFT NETWORKS 3.0          2       2       
356        DOS LM1.2X002                   3       3       
357        MICROSOFT NETWORKS 1.03                         3
358        DOS LANMAN2.1                   4       4       
359        LANMAN1.0                                       4      2      3
360        Windows for Workgroups 3.1a     5       5       5      3
361        LM1.2X002                                       6      4      4
362        LANMAN2.1                                       7      5      5
363        NT LM 0.12                              6       8      6
364   *
365   *  tim@fsg.com 09/29/95
366   *  Win2K added by matty 17/7/99
367   */
368   
369 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
370 #define ARCH_WIN95    0x2
371 #define ARCH_WINNT    0x4
372 #define ARCH_WIN2K    0xC      /* Win2K is like NT */
373 #define ARCH_OS2      0x14     /* Again OS/2 is like NT */
374 #define ARCH_SAMBA    0x20
375  
376 #define ARCH_ALL      0x3F
377  
378 /* List of supported protocols, most desired first */
379 static struct {
380   char *proto_name;
381   char *short_name;
382   int (*proto_reply_fn)(char *, char *);
383   int protocol_level;
384 } supported_protocols[] = {
385   {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
386   {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
387   {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
388   {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
389   {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
390   {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
391   {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
392   {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
393   {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
394   {NULL,NULL,NULL,0},
395 };
396
397
398 /****************************************************************************
399   reply to a negprot
400 ****************************************************************************/
401 int reply_negprot(connection_struct *conn, 
402                   char *inbuf,char *outbuf, int dum_size, 
403                   int dum_buffsize)
404 {
405   int outsize = set_message(outbuf,1,0,True);
406   int Index=0;
407   int choice= -1;
408   int protocol;
409   char *p;
410   int bcc = SVAL(smb_buf(inbuf),-2);
411   int arch = ARCH_ALL;
412   START_PROFILE(SMBnegprot);
413
414   p = smb_buf(inbuf)+1;
415   while (p < (smb_buf(inbuf) + bcc))
416     { 
417       Index++;
418       DEBUG(3,("Requested protocol [%s]\n",p));
419       if (strcsequal(p,"Windows for Workgroups 3.1a"))
420         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
421       else if (strcsequal(p,"DOS LM1.2X002"))
422         arch &= ( ARCH_WFWG | ARCH_WIN95 );
423       else if (strcsequal(p,"DOS LANMAN2.1"))
424         arch &= ( ARCH_WFWG | ARCH_WIN95 );
425       else if (strcsequal(p,"NT LM 0.12"))
426         arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
427       else if (strcsequal(p,"LANMAN2.1"))
428         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
429       else if (strcsequal(p,"LM1.2X002"))
430         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
431       else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
432         arch &= ARCH_WINNT;
433       else if (strcsequal(p,"XENIX CORE"))
434         arch &= ( ARCH_WINNT | ARCH_OS2 );
435       else if (strcsequal(p,"Samba")) {
436         arch = ARCH_SAMBA;
437         break;
438       }
439  
440       p += strlen(p) + 2;
441     }
442     
443   switch ( arch ) {
444   case ARCH_SAMBA:
445     set_remote_arch(RA_SAMBA);
446     break;
447   case ARCH_WFWG:
448     set_remote_arch(RA_WFWG);
449     break;
450   case ARCH_WIN95:
451     set_remote_arch(RA_WIN95);
452     break;
453   case ARCH_WINNT:
454    if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
455      set_remote_arch(RA_WIN2K);
456    else
457      set_remote_arch(RA_WINNT);
458     break;
459   case ARCH_WIN2K:
460     set_remote_arch(RA_WIN2K);
461     break;
462   case ARCH_OS2:
463     set_remote_arch(RA_OS2);
464     break;
465   default:
466     set_remote_arch(RA_UNKNOWN);
467     break;
468   }
469  
470   /* possibly reload - change of architecture */
471   reload_services(True);      
472     
473   /* Check for protocols, most desirable first */
474   for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
475     {
476       p = smb_buf(inbuf)+1;
477       Index = 0;
478       if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
479           (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
480         while (p < (smb_buf(inbuf) + bcc))
481           { 
482             if (strequal(p,supported_protocols[protocol].proto_name))
483               choice = Index;
484             Index++;
485             p += strlen(p) + 2;
486           }
487       if(choice != -1)
488         break;
489     }
490   
491   SSVAL(outbuf,smb_vwv0,choice);
492   if(choice != -1) {
493     extern fstring remote_proto;
494     fstrcpy(remote_proto,supported_protocols[protocol].short_name);
495     reload_services(True);          
496     outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
497     DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
498   }
499   else {
500     DEBUG(0,("No protocol supported !\n"));
501   }
502   SSVAL(outbuf,smb_vwv0,choice);
503   
504   DEBUG( 5, ( "negprot index=%d\n", choice ) );
505
506   END_PROFILE(SMBnegprot);
507   return(outsize);
508 }
509