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