r3946: Fix for bugid #2085 reported by Jason Mader <jason@ncac.gwu.edu>. Use consistent
[kai/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 enum protocol_types Protocol;
24 extern int max_recv;
25 BOOL global_encrypted_passwords_negotiated = False;
26 BOOL global_spnego_negotiated = False;
27 struct auth_context *negprot_global_auth_context = NULL;
28
29 static void get_challenge(char buff[8]) 
30 {
31         NTSTATUS nt_status;
32         const uint8 *cryptkey;
33
34         /* We might be called more than once, muliple negprots are premitted */
35         if (negprot_global_auth_context) {
36                 DEBUG(3, ("get challenge: is this a secondary negprot?  negprot_global_auth_context is non-NULL!\n"));
37                 (negprot_global_auth_context->free)(&negprot_global_auth_context);
38         }
39
40         DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
41         if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) {
42                 DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status)));
43                 smb_panic("cannot make_negprot_global_auth_context!\n");
44         }
45         DEBUG(10, ("get challenge: getting challenge\n"));
46         cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context);
47         memcpy(buff, cryptkey, 8);
48 }
49
50 /****************************************************************************
51  Reply for the core protocol.
52 ****************************************************************************/
53
54 static int reply_corep(char *inbuf, char *outbuf)
55 {
56         int outsize = set_message(outbuf,1,0,True);
57
58         Protocol = PROTOCOL_CORE;
59         
60         return outsize;
61 }
62
63 /****************************************************************************
64  Reply for the coreplus protocol.
65 ****************************************************************************/
66
67 static int reply_coreplus(char *inbuf, char *outbuf)
68 {
69         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
70         int outsize = set_message(outbuf,13,0,True);
71         SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
72                         readbraw and writebraw (possibly) */
73         /* Reply, SMBlockread, SMBwritelock supported. */
74         SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
75         SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */    
76
77         Protocol = PROTOCOL_COREPLUS;
78
79         return outsize;
80 }
81
82 /****************************************************************************
83  Reply for the lanman 1.0 protocol.
84 ****************************************************************************/
85
86 static int reply_lanman1(char *inbuf, char *outbuf)
87 {
88         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
89         int secword=0;
90         time_t t = time(NULL);
91
92         global_encrypted_passwords_negotiated = lp_encrypted_passwords();
93
94         if (lp_security()>=SEC_USER)
95                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
96         if (global_encrypted_passwords_negotiated)
97                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
98
99         set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
100         SSVAL(outbuf,smb_vwv1,secword); 
101         /* Create a token value and add it to the outgoing packet. */
102         if (global_encrypted_passwords_negotiated) {
103                 get_challenge(smb_buf(outbuf));
104                 SSVAL(outbuf,smb_vwv11, 8);
105         }
106
107         Protocol = PROTOCOL_LANMAN1;
108
109         /* Reply, SMBlockread, SMBwritelock supported. */
110         SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
111         SSVAL(outbuf,smb_vwv2,max_recv);
112         SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
113         SSVAL(outbuf,smb_vwv4,1);
114         SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
115                 readbraw writebraw (possibly) */
116         SIVAL(outbuf,smb_vwv6,sys_getpid());
117         SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
118
119         put_dos_date(outbuf,smb_vwv8,t);
120
121         return (smb_len(outbuf)+4);
122 }
123
124 /****************************************************************************
125  Reply for the lanman 2.0 protocol.
126 ****************************************************************************/
127
128 static int reply_lanman2(char *inbuf, char *outbuf)
129 {
130         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
131         int secword=0;
132         time_t t = time(NULL);
133
134         global_encrypted_passwords_negotiated = lp_encrypted_passwords();
135   
136         if (lp_security()>=SEC_USER)
137                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
138         if (global_encrypted_passwords_negotiated)
139                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
140
141         set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
142         SSVAL(outbuf,smb_vwv1,secword); 
143         SIVAL(outbuf,smb_vwv6,sys_getpid());
144
145         /* Create a token value and add it to the outgoing packet. */
146         if (global_encrypted_passwords_negotiated) {
147                 get_challenge(smb_buf(outbuf));
148                 SSVAL(outbuf,smb_vwv11, 8);
149         }
150
151         Protocol = PROTOCOL_LANMAN2;
152
153         /* Reply, SMBlockread, SMBwritelock supported. */
154         SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
155         SSVAL(outbuf,smb_vwv2,max_recv);
156         SSVAL(outbuf,smb_vwv3,lp_maxmux()); 
157         SSVAL(outbuf,smb_vwv4,1);
158         SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
159         SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
160         put_dos_date(outbuf,smb_vwv8,t);
161
162         return (smb_len(outbuf)+4);
163 }
164
165 /****************************************************************************
166  Generate the spnego negprot reply blob. Return the number of bytes used.
167 ****************************************************************************/
168
169 static int negprot_spnego(char *p)
170 {
171         DATA_BLOB blob;
172         nstring dos_name;
173         fstring unix_name;
174         uint8 guid[17];
175         const char *OIDs_krb5[] = {OID_KERBEROS5,
176                                    OID_KERBEROS5_OLD,
177                                    OID_NTLMSSP,
178                                    NULL};
179         const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
180         char *principal;
181         int len;
182
183         global_spnego_negotiated = True;
184
185         ZERO_STRUCT(guid);
186
187         safe_strcpy(unix_name, global_myname(), sizeof(unix_name)-1);
188         strlower_m(unix_name);
189         push_ascii_nstring(dos_name, unix_name);
190         safe_strcpy((char *)guid, dos_name, sizeof(guid)-1);
191
192 #ifdef DEVELOPER
193         /* valgrind fixer... */
194         {
195                 size_t sl = strlen(guid);
196                 if (sizeof(guid)-sl)
197                         memset(&guid[sl], '\0', sizeof(guid)-sl);
198         }
199 #endif
200
201 #if 0
202         /* strangely enough, NT does not sent the single OID NTLMSSP when
203            not a ADS member, it sends no OIDs at all
204
205            we can't do this until we teach our sesssion setup parser to know
206            about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)
207         */
208         if (lp_security() != SEC_ADS) {
209                 memcpy(p, guid, 16);
210                 return 16;
211         }
212 #endif
213         if (lp_security() != SEC_ADS) {
214                 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
215         } else {
216                 asprintf(&principal, "%s$@%s", guid, lp_realm());
217                 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
218                 free(principal);
219         }
220         memcpy(p, blob.data, blob.length);
221         len = blob.length;
222         data_blob_free(&blob);
223         return len;
224 }
225
226 /****************************************************************************
227  Reply for the nt protocol.
228 ****************************************************************************/
229
230 static int reply_nt1(char *inbuf, char *outbuf)
231 {
232         /* dual names + lock_and_read + nt SMBs + remote API calls */
233         int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
234                 CAP_LEVEL_II_OPLOCKS;
235
236         int secword=0;
237         time_t t = time(NULL);
238         char *p, *q;
239         BOOL negotiate_spnego = False;
240
241         global_encrypted_passwords_negotiated = lp_encrypted_passwords();
242
243         /* do spnego in user level security if the client
244            supports it and we can do encrypted passwords */
245         
246         if (global_encrypted_passwords_negotiated && 
247             (lp_security() != SEC_SHARE) &&
248             lp_use_spnego() &&
249             (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
250                 negotiate_spnego = True;
251                 capabilities |= CAP_EXTENDED_SECURITY;
252                 add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
253                 /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply (already
254                         partially constructed. */
255                 SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_EXTENDED_SECURITY);
256         }
257         
258         capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
259
260         if (lp_unix_extensions()) {
261                 capabilities |= CAP_UNIX;
262         }
263         
264         if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
265                 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
266         
267         if (SMB_OFF_T_BITS == 64)
268                 capabilities |= CAP_LARGE_FILES;
269
270         if (lp_readraw() && lp_writeraw())
271                 capabilities |= CAP_RAW_MODE;
272         
273         if (lp_nt_status_support())
274                 capabilities |= CAP_STATUS32;
275         
276         if (lp_host_msdfs())
277                 capabilities |= CAP_DFS;
278         
279         if (lp_security() >= SEC_USER)
280                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
281         if (global_encrypted_passwords_negotiated)
282                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
283         
284         if (lp_server_signing()) {
285                 if (lp_security() >= SEC_USER) {
286                         secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
287                         /* No raw mode with smb signing. */
288                         capabilities &= ~CAP_RAW_MODE;
289                         if (lp_server_signing() == Required)
290                                 secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
291                         srv_set_signing_negotiated();
292                 } else {
293                         DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
294                         if (lp_server_signing() == Required) {
295                                 exit_server("reply_nt1: smb signing required and share level security selected.");
296                         }
297                 }
298         }
299
300         set_message(outbuf,17,0,True);
301         
302         SCVAL(outbuf,smb_vwv1,secword);
303         
304         Protocol = PROTOCOL_NT1;
305         
306         SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
307         SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
308         SIVAL(outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */
309         SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
310         SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
311         SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
312         put_long_date(outbuf+smb_vwv11+1,t);
313         SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
314         
315         p = q = smb_buf(outbuf);
316         if (!negotiate_spnego) {
317                 /* Create a token value and add it to the outgoing packet. */
318                 if (global_encrypted_passwords_negotiated) {
319                         /* note that we do not send a challenge at all if
320                            we are using plaintext */
321                         get_challenge(p);
322                         SSVALS(outbuf,smb_vwv16+1,8);
323                         p += 8;
324                 }
325                 p += srvstr_push(outbuf, p, lp_workgroup(), -1, 
326                                  STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
327                 DEBUG(3,("not using SPNEGO\n"));
328         } else {
329                 int len = negprot_spnego(p);
330                 
331                 SSVALS(outbuf,smb_vwv16+1,len);
332                 p += len;
333                 DEBUG(3,("using SPNEGO\n"));
334         }
335         
336         SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
337         set_message_end(outbuf, p);
338         
339         return (smb_len(outbuf)+4);
340 }
341
342 /* these are the protocol lists used for auto architecture detection:
343
344 WinNT 3.51:
345 protocol [PC NETWORK PROGRAM 1.0]
346 protocol [XENIX CORE]
347 protocol [MICROSOFT NETWORKS 1.03]
348 protocol [LANMAN1.0]
349 protocol [Windows for Workgroups 3.1a]
350 protocol [LM1.2X002]
351 protocol [LANMAN2.1]
352 protocol [NT LM 0.12]
353
354 Win95:
355 protocol [PC NETWORK PROGRAM 1.0]
356 protocol [XENIX CORE]
357 protocol [MICROSOFT NETWORKS 1.03]
358 protocol [LANMAN1.0]
359 protocol [Windows for Workgroups 3.1a]
360 protocol [LM1.2X002]
361 protocol [LANMAN2.1]
362 protocol [NT LM 0.12]
363
364 Win2K:
365 protocol [PC NETWORK PROGRAM 1.0]
366 protocol [LANMAN1.0]
367 protocol [Windows for Workgroups 3.1a]
368 protocol [LM1.2X002]
369 protocol [LANMAN2.1]
370 protocol [NT LM 0.12]
371
372 OS/2:
373 protocol [PC NETWORK PROGRAM 1.0]
374 protocol [XENIX CORE]
375 protocol [LANMAN1.0]
376 protocol [LM1.2X002]
377 protocol [LANMAN2.1]
378 */
379
380 /*
381   * Modified to recognize the architecture of the remote machine better.
382   *
383   * This appears to be the matrix of which protocol is used by which
384   * MS product.
385        Protocol                       WfWg    Win95   WinNT  Win2K  OS/2
386        PC NETWORK PROGRAM 1.0          1       1       1      1      1
387        XENIX CORE                                      2             2
388        MICROSOFT NETWORKS 3.0          2       2       
389        DOS LM1.2X002                   3       3       
390        MICROSOFT NETWORKS 1.03                         3
391        DOS LANMAN2.1                   4       4       
392        LANMAN1.0                                       4      2      3
393        Windows for Workgroups 3.1a     5       5       5      3
394        LM1.2X002                                       6      4      4
395        LANMAN2.1                                       7      5      5
396        NT LM 0.12                              6       8      6
397   *
398   *  tim@fsg.com 09/29/95
399   *  Win2K added by matty 17/7/99
400   */
401   
402 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
403 #define ARCH_WIN95    0x2
404 #define ARCH_WINNT    0x4
405 #define ARCH_WIN2K    0xC      /* Win2K is like NT */
406 #define ARCH_OS2      0x14     /* Again OS/2 is like NT */
407 #define ARCH_SAMBA    0x20
408 #define ARCH_CIFSFS   0x40
409  
410 #define ARCH_ALL      0x7F
411  
412 /* List of supported protocols, most desired first */
413 static const struct {
414         const char *proto_name;
415         const char *short_name;
416         int (*proto_reply_fn)(char *, char *);
417         int protocol_level;
418 } supported_protocols[] = {
419         {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
420         {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
421         {"POSIX 2",                 "NT1",      reply_nt1,      PROTOCOL_NT1},
422         {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
423         {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
424         {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
425         {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
426         {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
427         {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
428         {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
429         {NULL,NULL,NULL,0},
430 };
431
432 /****************************************************************************
433  Reply to a negprot.
434 ****************************************************************************/
435
436 int reply_negprot(connection_struct *conn, 
437                   char *inbuf,char *outbuf, int dum_size, 
438                   int dum_buffsize)
439 {
440         int outsize = set_message(outbuf,1,0,True);
441         int Index=0;
442         int choice= -1;
443         int protocol;
444         char *p;
445         int bcc = SVAL(smb_buf(inbuf),-2);
446         int arch = ARCH_ALL;
447
448         static BOOL done_negprot = False;
449
450         START_PROFILE(SMBnegprot);
451
452         if (done_negprot) {
453                 END_PROFILE(SMBnegprot);
454                 exit_server("multiple negprot's are not permitted");
455         }
456         done_negprot = True;
457
458         p = smb_buf(inbuf)+1;
459         while (p < (smb_buf(inbuf) + bcc)) { 
460                 Index++;
461                 DEBUG(3,("Requested protocol [%s]\n",p));
462                 if (strcsequal(p,"Windows for Workgroups 3.1a"))
463                         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
464                 else if (strcsequal(p,"DOS LM1.2X002"))
465                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
466                 else if (strcsequal(p,"DOS LANMAN2.1"))
467                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
468                 else if (strcsequal(p,"NT LM 0.12"))
469                         arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K | ARCH_CIFSFS);
470                 else if (strcsequal(p,"LANMAN2.1"))
471                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
472                 else if (strcsequal(p,"LM1.2X002"))
473                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
474                 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
475                         arch &= ARCH_WINNT;
476                 else if (strcsequal(p,"XENIX CORE"))
477                         arch &= ( ARCH_WINNT | ARCH_OS2 );
478                 else if (strcsequal(p,"Samba")) {
479                         arch = ARCH_SAMBA;
480                         break;
481                 } else if (strcsequal(p,"POSIX 2")) {
482                         arch = ARCH_CIFSFS;
483                         break;
484                 }
485  
486                 p += strlen(p) + 2;
487         }
488
489         /* CIFSFS can send one arch only, NT LM 0.12. */
490         if (Index == 1 && (arch & ARCH_CIFSFS)) {
491                 arch = ARCH_CIFSFS;
492         }
493
494         switch ( arch ) {
495                 case ARCH_CIFSFS:
496                         set_remote_arch(RA_CIFSFS);
497                         break;
498                 case ARCH_SAMBA:
499                         set_remote_arch(RA_SAMBA);
500                         break;
501                 case ARCH_WFWG:
502                         set_remote_arch(RA_WFWG);
503                         break;
504                 case ARCH_WIN95:
505                         set_remote_arch(RA_WIN95);
506                         break;
507                 case ARCH_WINNT:
508                         if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
509                                 set_remote_arch(RA_WIN2K);
510                         else
511                                 set_remote_arch(RA_WINNT);
512                         break;
513                 case ARCH_WIN2K:
514                         set_remote_arch(RA_WIN2K);
515                         break;
516                 case ARCH_OS2:
517                         set_remote_arch(RA_OS2);
518                         break;
519                 default:
520                         set_remote_arch(RA_UNKNOWN);
521                 break;
522         }
523  
524         /* possibly reload - change of architecture */
525         reload_services(True);      
526     
527         /* Check for protocols, most desirable first */
528         for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
529                 p = smb_buf(inbuf)+1;
530                 Index = 0;
531                 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
532                                 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
533                         while (p < (smb_buf(inbuf) + bcc)) { 
534                                 if (strequal(p,supported_protocols[protocol].proto_name))
535                                         choice = Index;
536                                 Index++;
537                                 p += strlen(p) + 2;
538                         }
539                 if(choice != -1)
540                         break;
541         }
542   
543         SSVAL(outbuf,smb_vwv0,choice);
544         if(choice != -1) {
545                 extern fstring remote_proto;
546                 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
547                 reload_services(True);          
548                 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
549                 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
550         } else {
551                 DEBUG(0,("No protocol supported !\n"));
552         }
553         SSVAL(outbuf,smb_vwv0,choice);
554   
555         DEBUG( 5, ( "negprot index=%d\n", choice ) );
556
557         if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) {
558                 exit_server("SMB signing is required and client negotiated a downlevel protocol");
559         }
560
561         END_PROFILE(SMBnegprot);
562         return(outsize);
563 }