Modified fix for bugid #784. Based on a patch from moriyama@miraclelinux.com (MORIYAM...
[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 int 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         }
253         
254         capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
255
256         if (lp_unix_extensions()) {
257                 capabilities |= CAP_UNIX;
258         }
259         
260         if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
261                 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
262         
263         if (SMB_OFF_T_BITS == 64)
264                 capabilities |= CAP_LARGE_FILES;
265
266         if (lp_readraw() && lp_writeraw())
267                 capabilities |= CAP_RAW_MODE;
268         
269         /* allow for disabling unicode */
270         if (lp_unicode())
271                 capabilities |= CAP_UNICODE;
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  
409 #define ARCH_ALL      0x3F
410  
411 /* List of supported protocols, most desired first */
412 static const struct {
413         const char *proto_name;
414         const char *short_name;
415         int (*proto_reply_fn)(char *, char *);
416         int protocol_level;
417 } supported_protocols[] = {
418         {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
419         {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
420         {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
421         {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
422         {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
423         {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
424         {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
425         {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
426         {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
427         {NULL,NULL,NULL,0},
428 };
429
430 /****************************************************************************
431  Reply to a negprot.
432 ****************************************************************************/
433
434 int reply_negprot(connection_struct *conn, 
435                   char *inbuf,char *outbuf, int dum_size, 
436                   int dum_buffsize)
437 {
438         int outsize = set_message(outbuf,1,0,True);
439         int Index=0;
440         int choice= -1;
441         int protocol;
442         char *p;
443         int bcc = SVAL(smb_buf(inbuf),-2);
444         int arch = ARCH_ALL;
445
446         static BOOL done_negprot = False;
447
448         START_PROFILE(SMBnegprot);
449
450         if (done_negprot) {
451                 END_PROFILE(SMBnegprot);
452                 exit_server("multiple negprot's are not permitted");
453         }
454         done_negprot = True;
455
456         p = smb_buf(inbuf)+1;
457         while (p < (smb_buf(inbuf) + bcc)) { 
458                 Index++;
459                 DEBUG(3,("Requested protocol [%s]\n",p));
460                 if (strcsequal(p,"Windows for Workgroups 3.1a"))
461                         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
462                 else if (strcsequal(p,"DOS LM1.2X002"))
463                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
464                 else if (strcsequal(p,"DOS LANMAN2.1"))
465                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
466                 else if (strcsequal(p,"NT LM 0.12"))
467                         arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
468                 else if (strcsequal(p,"LANMAN2.1"))
469                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
470                 else if (strcsequal(p,"LM1.2X002"))
471                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
472                 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
473                         arch &= ARCH_WINNT;
474                 else if (strcsequal(p,"XENIX CORE"))
475                         arch &= ( ARCH_WINNT | ARCH_OS2 );
476                 else if (strcsequal(p,"Samba")) {
477                         arch = ARCH_SAMBA;
478                         break;
479                 }
480  
481                 p += strlen(p) + 2;
482         }
483     
484         switch ( arch ) {
485                 case ARCH_SAMBA:
486                         set_remote_arch(RA_SAMBA);
487                         break;
488                 case ARCH_WFWG:
489                         set_remote_arch(RA_WFWG);
490                         break;
491                 case ARCH_WIN95:
492                         set_remote_arch(RA_WIN95);
493                         break;
494                 case ARCH_WINNT:
495                         if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
496                                 set_remote_arch(RA_WIN2K);
497                         else
498                                 set_remote_arch(RA_WINNT);
499                         break;
500                 case ARCH_WIN2K:
501                         set_remote_arch(RA_WIN2K);
502                         break;
503                 case ARCH_OS2:
504                         set_remote_arch(RA_OS2);
505                         break;
506                 default:
507                         set_remote_arch(RA_UNKNOWN);
508                 break;
509         }
510  
511         /* possibly reload - change of architecture */
512         reload_services(True);      
513     
514         /* Check for protocols, most desirable first */
515         for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
516                 p = smb_buf(inbuf)+1;
517                 Index = 0;
518                 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
519                                 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
520                         while (p < (smb_buf(inbuf) + bcc)) { 
521                                 if (strequal(p,supported_protocols[protocol].proto_name))
522                                         choice = Index;
523                                 Index++;
524                                 p += strlen(p) + 2;
525                         }
526                 if(choice != -1)
527                         break;
528         }
529   
530         SSVAL(outbuf,smb_vwv0,choice);
531         if(choice != -1) {
532                 extern fstring remote_proto;
533                 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
534                 reload_services(True);          
535                 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
536                 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
537         } else {
538                 DEBUG(0,("No protocol supported !\n"));
539         }
540         SSVAL(outbuf,smb_vwv0,choice);
541   
542         DEBUG( 5, ( "negprot index=%d\n", choice ) );
543
544         if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) {
545                 exit_server("SMB signing is required and client negotiated a downlevel protocol");
546         }
547
548         END_PROFILE(SMBnegprot);
549         return(outsize);
550 }