port latest changes from SAMBA_3_0 tree
[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         uint8 guid[17];
173         const char *OIDs_krb5[] = {OID_KERBEROS5,
174                                    OID_KERBEROS5_OLD,
175                                    OID_NTLMSSP,
176                                    NULL};
177         const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
178         char *principal;
179         int len;
180
181         global_spnego_negotiated = True;
182
183         ZERO_STRUCT(guid);
184         safe_strcpy((char *)guid, global_myname(), sizeof(guid)-1);
185
186 #ifdef DEVELOPER
187         /* valgrind fixer... */
188         {
189                 size_t sl = strlen(guid);
190                 if (sizeof(guid)-sl)
191                         memset(&guid[sl], '\0', sizeof(guid)-sl);
192         }
193 #endif
194
195         strlower_m((char *)guid);
196
197 #if 0
198         /* strangely enough, NT does not sent the single OID NTLMSSP when
199            not a ADS member, it sends no OIDs at all
200
201            we can't do this until we teach our sesssion setup parser to know
202            about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)
203         */
204         if (lp_security() != SEC_ADS) {
205                 memcpy(p, guid, 16);
206                 return 16;
207         }
208 #endif
209         if (lp_security() != SEC_ADS) {
210                 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
211         } else {
212                 asprintf(&principal, "%s$@%s", guid, lp_realm());
213                 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
214                 free(principal);
215         }
216         memcpy(p, blob.data, blob.length);
217         len = blob.length;
218         data_blob_free(&blob);
219         return len;
220 }
221
222 /****************************************************************************
223  Reply for the nt protocol.
224 ****************************************************************************/
225
226 static int reply_nt1(char *inbuf, char *outbuf)
227 {
228         /* dual names + lock_and_read + nt SMBs + remote API calls */
229         int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
230                 CAP_LEVEL_II_OPLOCKS;
231
232         int secword=0;
233         time_t t = time(NULL);
234         char *p, *q;
235         BOOL negotiate_spnego = False;
236
237         global_encrypted_passwords_negotiated = lp_encrypted_passwords();
238
239         /* do spnego in user level security if the client
240            supports it and we can do encrypted passwords */
241         
242         if (global_encrypted_passwords_negotiated && 
243             (lp_security() != SEC_SHARE) &&
244             lp_use_spnego() &&
245             (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
246                 negotiate_spnego = True;
247                 capabilities |= CAP_EXTENDED_SECURITY;
248         }
249         
250         capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
251
252         if (lp_unix_extensions()) {
253                 capabilities |= CAP_UNIX;
254         }
255         
256         if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
257                 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
258         
259         if (SMB_OFF_T_BITS == 64)
260                 capabilities |= CAP_LARGE_FILES;
261
262         if (lp_readraw() && lp_writeraw())
263                 capabilities |= CAP_RAW_MODE;
264         
265         /* allow for disabling unicode */
266         if (lp_unicode())
267                 capabilities |= CAP_UNICODE;
268
269         if (lp_nt_status_support())
270                 capabilities |= CAP_STATUS32;
271         
272         if (lp_host_msdfs())
273                 capabilities |= CAP_DFS;
274         
275         if (lp_security() >= SEC_USER)
276                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
277         if (global_encrypted_passwords_negotiated)
278                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
279         
280         if (lp_server_signing()) {
281                 if (lp_security() >= SEC_USER) {
282                         secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
283                         /* No raw mode with smb signing. */
284                         capabilities &= ~CAP_RAW_MODE;
285                         if (lp_server_signing() == Required)
286                                 secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
287                         srv_set_signing_negotiated();
288                 } else {
289                         DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
290                         if (lp_server_signing() == Required) {
291                                 exit_server("reply_nt1: smb signing required and share level security selected.");
292                         }
293                 }
294         }
295
296         set_message(outbuf,17,0,True);
297         
298         SCVAL(outbuf,smb_vwv1,secword);
299         
300         Protocol = PROTOCOL_NT1;
301         
302         SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
303         SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
304         SIVAL(outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */
305         SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
306         SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
307         SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
308         put_long_date(outbuf+smb_vwv11+1,t);
309         SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
310         
311         p = q = smb_buf(outbuf);
312         if (!negotiate_spnego) {
313                 /* Create a token value and add it to the outgoing packet. */
314                 if (global_encrypted_passwords_negotiated) {
315                         /* note that we do not send a challenge at all if
316                            we are using plaintext */
317                         get_challenge(p);
318                         SSVALS(outbuf,smb_vwv16+1,8);
319                         p += 8;
320                 }
321                 p += srvstr_push(outbuf, p, lp_workgroup(), -1, 
322                                  STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
323                 DEBUG(3,("not using SPNEGO\n"));
324         } else {
325                 int len = negprot_spnego(p);
326                 
327                 SSVALS(outbuf,smb_vwv16+1,len);
328                 p += len;
329                 DEBUG(3,("using SPNEGO\n"));
330         }
331         
332         SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
333         set_message_end(outbuf, p);
334         
335         return (smb_len(outbuf)+4);
336 }
337
338 /* these are the protocol lists used for auto architecture detection:
339
340 WinNT 3.51:
341 protocol [PC NETWORK PROGRAM 1.0]
342 protocol [XENIX CORE]
343 protocol [MICROSOFT NETWORKS 1.03]
344 protocol [LANMAN1.0]
345 protocol [Windows for Workgroups 3.1a]
346 protocol [LM1.2X002]
347 protocol [LANMAN2.1]
348 protocol [NT LM 0.12]
349
350 Win95:
351 protocol [PC NETWORK PROGRAM 1.0]
352 protocol [XENIX CORE]
353 protocol [MICROSOFT NETWORKS 1.03]
354 protocol [LANMAN1.0]
355 protocol [Windows for Workgroups 3.1a]
356 protocol [LM1.2X002]
357 protocol [LANMAN2.1]
358 protocol [NT LM 0.12]
359
360 Win2K:
361 protocol [PC NETWORK PROGRAM 1.0]
362 protocol [LANMAN1.0]
363 protocol [Windows for Workgroups 3.1a]
364 protocol [LM1.2X002]
365 protocol [LANMAN2.1]
366 protocol [NT LM 0.12]
367
368 OS/2:
369 protocol [PC NETWORK PROGRAM 1.0]
370 protocol [XENIX CORE]
371 protocol [LANMAN1.0]
372 protocol [LM1.2X002]
373 protocol [LANMAN2.1]
374 */
375
376 /*
377   * Modified to recognize the architecture of the remote machine better.
378   *
379   * This appears to be the matrix of which protocol is used by which
380   * MS product.
381        Protocol                       WfWg    Win95   WinNT  Win2K  OS/2
382        PC NETWORK PROGRAM 1.0          1       1       1      1      1
383        XENIX CORE                                      2             2
384        MICROSOFT NETWORKS 3.0          2       2       
385        DOS LM1.2X002                   3       3       
386        MICROSOFT NETWORKS 1.03                         3
387        DOS LANMAN2.1                   4       4       
388        LANMAN1.0                                       4      2      3
389        Windows for Workgroups 3.1a     5       5       5      3
390        LM1.2X002                                       6      4      4
391        LANMAN2.1                                       7      5      5
392        NT LM 0.12                              6       8      6
393   *
394   *  tim@fsg.com 09/29/95
395   *  Win2K added by matty 17/7/99
396   */
397   
398 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
399 #define ARCH_WIN95    0x2
400 #define ARCH_WINNT    0x4
401 #define ARCH_WIN2K    0xC      /* Win2K is like NT */
402 #define ARCH_OS2      0x14     /* Again OS/2 is like NT */
403 #define ARCH_SAMBA    0x20
404  
405 #define ARCH_ALL      0x3F
406  
407 /* List of supported protocols, most desired first */
408 static const struct {
409         const char *proto_name;
410         const char *short_name;
411         int (*proto_reply_fn)(char *, char *);
412         int protocol_level;
413 } supported_protocols[] = {
414         {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
415         {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
416         {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
417         {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
418         {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
419         {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
420         {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
421         {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
422         {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
423         {NULL,NULL,NULL,0},
424 };
425
426 /****************************************************************************
427  Reply to a negprot.
428 ****************************************************************************/
429
430 int reply_negprot(connection_struct *conn, 
431                   char *inbuf,char *outbuf, int dum_size, 
432                   int dum_buffsize)
433 {
434         int outsize = set_message(outbuf,1,0,True);
435         int Index=0;
436         int choice= -1;
437         int protocol;
438         char *p;
439         int bcc = SVAL(smb_buf(inbuf),-2);
440         int arch = ARCH_ALL;
441
442         static BOOL done_negprot = False;
443
444         START_PROFILE(SMBnegprot);
445
446         if (done_negprot) {
447                 END_PROFILE(SMBnegprot);
448                 exit_server("multiple negprot's are not permitted");
449         }
450         done_negprot = True;
451
452         p = smb_buf(inbuf)+1;
453         while (p < (smb_buf(inbuf) + bcc)) { 
454                 Index++;
455                 DEBUG(3,("Requested protocol [%s]\n",p));
456                 if (strcsequal(p,"Windows for Workgroups 3.1a"))
457                         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
458                 else if (strcsequal(p,"DOS LM1.2X002"))
459                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
460                 else if (strcsequal(p,"DOS LANMAN2.1"))
461                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
462                 else if (strcsequal(p,"NT LM 0.12"))
463                         arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
464                 else if (strcsequal(p,"LANMAN2.1"))
465                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
466                 else if (strcsequal(p,"LM1.2X002"))
467                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
468                 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
469                         arch &= ARCH_WINNT;
470                 else if (strcsequal(p,"XENIX CORE"))
471                         arch &= ( ARCH_WINNT | ARCH_OS2 );
472                 else if (strcsequal(p,"Samba")) {
473                         arch = ARCH_SAMBA;
474                         break;
475                 }
476  
477                 p += strlen(p) + 2;
478         }
479     
480         switch ( arch ) {
481                 case ARCH_SAMBA:
482                         set_remote_arch(RA_SAMBA);
483                         break;
484                 case ARCH_WFWG:
485                         set_remote_arch(RA_WFWG);
486                         break;
487                 case ARCH_WIN95:
488                         set_remote_arch(RA_WIN95);
489                         break;
490                 case ARCH_WINNT:
491                         if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
492                                 set_remote_arch(RA_WIN2K);
493                         else
494                                 set_remote_arch(RA_WINNT);
495                         break;
496                 case ARCH_WIN2K:
497                         set_remote_arch(RA_WIN2K);
498                         break;
499                 case ARCH_OS2:
500                         set_remote_arch(RA_OS2);
501                         break;
502                 default:
503                         set_remote_arch(RA_UNKNOWN);
504                 break;
505         }
506  
507         /* possibly reload - change of architecture */
508         reload_services(True);      
509     
510         /* Check for protocols, most desirable first */
511         for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
512                 p = smb_buf(inbuf)+1;
513                 Index = 0;
514                 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
515                                 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
516                         while (p < (smb_buf(inbuf) + bcc)) { 
517                                 if (strequal(p,supported_protocols[protocol].proto_name))
518                                         choice = Index;
519                                 Index++;
520                                 p += strlen(p) + 2;
521                         }
522                 if(choice != -1)
523                         break;
524         }
525   
526         SSVAL(outbuf,smb_vwv0,choice);
527         if(choice != -1) {
528                 extern fstring remote_proto;
529                 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
530                 reload_services(True);          
531                 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
532                 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
533         } else {
534                 DEBUG(0,("No protocol supported !\n"));
535         }
536         SSVAL(outbuf,smb_vwv0,choice);
537   
538         DEBUG( 5, ( "negprot index=%d\n", choice ) );
539
540         if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) {
541                 exit_server("SMB signing is required and client negotiated a downlevel protocol");
542         }
543
544         END_PROFILE(SMBnegprot);
545         return(outsize);
546 }