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