don't do an ADS init when not in ADS mode
[jra/samba/.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", get_nt_error_msg(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|CAP_STATUS32;
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         
249         if (SMB_OFF_T_BITS == 64) {
250                 capabilities |= CAP_LARGE_FILES;
251         }
252         
253         if (lp_readraw() && lp_writeraw()) {
254                 capabilities |= CAP_RAW_MODE;
255         }
256         
257         /* allow for disabling unicode */
258         if (lp_unicode()) {
259                 capabilities |= CAP_UNICODE;
260         }
261         
262         if (lp_host_msdfs())
263                 capabilities |= CAP_DFS;
264         
265         if (lp_security() >= SEC_USER) secword |= 1;
266         if (global_encrypted_passwords_negotiated) secword |= 2;
267         
268         set_message(outbuf,17,0,True);
269         
270         SCVAL(outbuf,smb_vwv1,secword);
271         
272         Protocol = PROTOCOL_NT1;
273         
274         SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
275         SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
276         SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
277         SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
278         SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
279         SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
280         put_long_date(outbuf+smb_vwv11+1,t);
281         SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
282         
283         p = q = smb_buf(outbuf);
284         if (!negotiate_spnego) {
285                 /* Create a token value and add it to the outgoing packet. */
286                 if (global_encrypted_passwords_negotiated) {
287                         get_challenge(p);
288                 }
289                 SSVALS(outbuf,smb_vwv16+1,8);
290                 p += 8;
291                 p += srvstr_push(outbuf, p, global_myworkgroup, -1, 
292                                  STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
293                 DEBUG(3,("not using SPNEGO\n"));
294         } else {
295                 int len = negprot_spnego(p);
296                 
297                 SSVALS(outbuf,smb_vwv16+1,len);
298                 p += len;
299                 DEBUG(3,("using SPNEGO\n"));
300         }
301         
302         SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
303         set_message_end(outbuf, p);
304         
305         return (smb_len(outbuf)+4);
306 }
307
308 /* these are the protocol lists used for auto architecture detection:
309
310 WinNT 3.51:
311 protocol [PC NETWORK PROGRAM 1.0]
312 protocol [XENIX CORE]
313 protocol [MICROSOFT NETWORKS 1.03]
314 protocol [LANMAN1.0]
315 protocol [Windows for Workgroups 3.1a]
316 protocol [LM1.2X002]
317 protocol [LANMAN2.1]
318 protocol [NT LM 0.12]
319
320 Win95:
321 protocol [PC NETWORK PROGRAM 1.0]
322 protocol [XENIX CORE]
323 protocol [MICROSOFT NETWORKS 1.03]
324 protocol [LANMAN1.0]
325 protocol [Windows for Workgroups 3.1a]
326 protocol [LM1.2X002]
327 protocol [LANMAN2.1]
328 protocol [NT LM 0.12]
329
330 Win2K:
331 protocol [PC NETWORK PROGRAM 1.0]
332 protocol [LANMAN1.0]
333 protocol [Windows for Workgroups 3.1a]
334 protocol [LM1.2X002]
335 protocol [LANMAN2.1]
336 protocol [NT LM 0.12]
337
338 OS/2:
339 protocol [PC NETWORK PROGRAM 1.0]
340 protocol [XENIX CORE]
341 protocol [LANMAN1.0]
342 protocol [LM1.2X002]
343 protocol [LANMAN2.1]
344 */
345
346 /*
347   * Modified to recognize the architecture of the remote machine better.
348   *
349   * This appears to be the matrix of which protocol is used by which
350   * MS product.
351        Protocol                       WfWg    Win95   WinNT  Win2K  OS/2
352        PC NETWORK PROGRAM 1.0          1       1       1      1      1
353        XENIX CORE                                      2             2
354        MICROSOFT NETWORKS 3.0          2       2       
355        DOS LM1.2X002                   3       3       
356        MICROSOFT NETWORKS 1.03                         3
357        DOS LANMAN2.1                   4       4       
358        LANMAN1.0                                       4      2      3
359        Windows for Workgroups 3.1a     5       5       5      3
360        LM1.2X002                                       6      4      4
361        LANMAN2.1                                       7      5      5
362        NT LM 0.12                              6       8      6
363   *
364   *  tim@fsg.com 09/29/95
365   *  Win2K added by matty 17/7/99
366   */
367   
368 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
369 #define ARCH_WIN95    0x2
370 #define ARCH_WINNT    0x4
371 #define ARCH_WIN2K    0xC      /* Win2K is like NT */
372 #define ARCH_OS2      0x14     /* Again OS/2 is like NT */
373 #define ARCH_SAMBA    0x20
374  
375 #define ARCH_ALL      0x3F
376  
377 /* List of supported protocols, most desired first */
378 static struct {
379   char *proto_name;
380   char *short_name;
381   int (*proto_reply_fn)(char *, char *);
382   int protocol_level;
383 } supported_protocols[] = {
384   {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
385   {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
386   {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
387   {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
388   {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
389   {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
390   {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
391   {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
392   {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
393   {NULL,NULL,NULL,0},
394 };
395
396
397 /****************************************************************************
398   reply to a negprot
399 ****************************************************************************/
400 int reply_negprot(connection_struct *conn, 
401                   char *inbuf,char *outbuf, int dum_size, 
402                   int dum_buffsize)
403 {
404   int outsize = set_message(outbuf,1,0,True);
405   int Index=0;
406   int choice= -1;
407   int protocol;
408   char *p;
409   int bcc = SVAL(smb_buf(inbuf),-2);
410   int arch = ARCH_ALL;
411   START_PROFILE(SMBnegprot);
412
413   p = smb_buf(inbuf)+1;
414   while (p < (smb_buf(inbuf) + bcc))
415     { 
416       Index++;
417       DEBUG(3,("Requested protocol [%s]\n",p));
418       if (strcsequal(p,"Windows for Workgroups 3.1a"))
419         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
420       else if (strcsequal(p,"DOS LM1.2X002"))
421         arch &= ( ARCH_WFWG | ARCH_WIN95 );
422       else if (strcsequal(p,"DOS LANMAN2.1"))
423         arch &= ( ARCH_WFWG | ARCH_WIN95 );
424       else if (strcsequal(p,"NT LM 0.12"))
425         arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
426       else if (strcsequal(p,"LANMAN2.1"))
427         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
428       else if (strcsequal(p,"LM1.2X002"))
429         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
430       else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
431         arch &= ARCH_WINNT;
432       else if (strcsequal(p,"XENIX CORE"))
433         arch &= ( ARCH_WINNT | ARCH_OS2 );
434       else if (strcsequal(p,"Samba")) {
435         arch = ARCH_SAMBA;
436         break;
437       }
438  
439       p += strlen(p) + 2;
440     }
441     
442   switch ( arch ) {
443   case ARCH_SAMBA:
444     set_remote_arch(RA_SAMBA);
445     break;
446   case ARCH_WFWG:
447     set_remote_arch(RA_WFWG);
448     break;
449   case ARCH_WIN95:
450     set_remote_arch(RA_WIN95);
451     break;
452   case ARCH_WINNT:
453    if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
454      set_remote_arch(RA_WIN2K);
455    else
456      set_remote_arch(RA_WINNT);
457     break;
458   case ARCH_WIN2K:
459     set_remote_arch(RA_WIN2K);
460     break;
461   case ARCH_OS2:
462     set_remote_arch(RA_OS2);
463     break;
464   default:
465     set_remote_arch(RA_UNKNOWN);
466     break;
467   }
468  
469   /* possibly reload - change of architecture */
470   reload_services(True);      
471     
472   /* Check for protocols, most desirable first */
473   for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
474     {
475       p = smb_buf(inbuf)+1;
476       Index = 0;
477       if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
478           (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
479         while (p < (smb_buf(inbuf) + bcc))
480           { 
481             if (strequal(p,supported_protocols[protocol].proto_name))
482               choice = Index;
483             Index++;
484             p += strlen(p) + 2;
485           }
486       if(choice != -1)
487         break;
488     }
489   
490   SSVAL(outbuf,smb_vwv0,choice);
491   if(choice != -1) {
492     extern fstring remote_proto;
493     fstrcpy(remote_proto,supported_protocols[protocol].short_name);
494     reload_services(True);          
495     outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
496     DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
497   }
498   else {
499     DEBUG(0,("No protocol supported !\n"));
500   }
501   SSVAL(outbuf,smb_vwv0,choice);
502   
503   DEBUG( 5, ( "negprot index=%d\n", choice ) );
504
505   END_PROFILE(SMBnegprot);
506   return(outsize);
507 }
508