r890: convert samba4 to use [u]int8_t instead of [u]int8
[jelmer/samba4-debian.git] / source / smb_server / 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 /* initialise the auth_context for this server and return the cryptkey */
24 static void get_challenge(struct server_context *smb, char buff[8]) 
25 {
26         NTSTATUS nt_status;
27         const uint8_t *cryptkey;
28
29         /* muliple negprots are not premitted */
30         if (smb->negotiate.auth_context) {
31                 DEBUG(3,("get challenge: is this a secondary negprot?  auth_context is non-NULL!\n"));
32                 smb_panic("secondary negprot");
33         }
34
35         DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
36
37         nt_status = make_auth_context_subsystem(&smb->negotiate.auth_context);
38
39         if (!NT_STATUS_IS_OK(nt_status)) {
40                 DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status)));
41                 smb_panic("cannot make_negprot_global_auth_context!\n");
42         }
43
44         DEBUG(10, ("get challenge: getting challenge\n"));
45         cryptkey = smb->negotiate.auth_context->get_ntlm_challenge(smb->negotiate.auth_context);
46         memcpy(buff, cryptkey, 8);
47 }
48
49 /****************************************************************************
50  Reply for the core protocol.
51 ****************************************************************************/
52 static void reply_corep(struct request_context *req, uint16_t choice)
53 {
54         req_setup_reply(req, 1, 0);
55
56         SSVAL(req->out.vwv, VWV(0), choice);
57
58         req->smb->negotiate.protocol = PROTOCOL_CORE;
59
60         req_send_reply(req);
61 }
62
63 /****************************************************************************
64  Reply for the coreplus protocol.
65 this is quite incomplete - we only fill in a small part of the reply, but as nobody uses
66 this any more it probably doesn't matter
67 ****************************************************************************/
68 static void reply_coreplus(struct request_context *req, uint16_t choice)
69 {
70         uint16_t raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
71
72         req_setup_reply(req, 13, 0);
73
74         /* Reply, SMBlockread, SMBwritelock supported. */
75         SCVAL(req->out.hdr,HDR_FLG,
76               CVAL(req->out.hdr, HDR_FLG) | FLAG_SUPPORT_LOCKREAD);
77
78         SSVAL(req->out.vwv, VWV(0), choice);
79         SSVAL(req->out.vwv, VWV(1), 0x1); /* user level security, don't encrypt */      
80
81         /* tell redirector we support
82            readbraw and writebraw (possibly) */
83         SSVAL(req->out.vwv, VWV(5), raw); 
84
85         req->smb->negotiate.protocol = PROTOCOL_COREPLUS;
86
87         req_send_reply(req);
88 }
89
90 /****************************************************************************
91  Reply for the lanman 1.0 protocol.
92 ****************************************************************************/
93 static void reply_lanman1(struct request_context *req, uint16_t choice)
94 {
95         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
96         int secword=0;
97         time_t t = req->request_time.tv_sec;
98
99         req->smb->negotiate.encrypted_passwords = lp_encrypted_passwords();
100
101         if (lp_security() != SEC_SHARE)
102                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
103
104         if (req->smb->negotiate.encrypted_passwords)
105                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
106
107         req->smb->negotiate.protocol = PROTOCOL_LANMAN1;
108
109         req_setup_reply(req, 13, req->smb->negotiate.encrypted_passwords ? 8 : 0);
110
111         /* SMBlockread, SMBwritelock supported. */
112         SCVAL(req->out.hdr,HDR_FLG,
113               CVAL(req->out.hdr, HDR_FLG) | FLAG_SUPPORT_LOCKREAD);
114
115         SSVAL(req->out.vwv, VWV(0), choice);
116         SSVAL(req->out.vwv, VWV(1), secword); 
117         SSVAL(req->out.vwv, VWV(2), req->smb->negotiate.max_recv);
118         SSVAL(req->out.vwv, VWV(3), lp_maxmux());
119         SSVAL(req->out.vwv, VWV(4), 1);
120         SSVAL(req->out.vwv, VWV(5), raw); 
121         SIVAL(req->out.vwv, VWV(6), req->smb->pid);
122         srv_push_dos_date(req->smb, req->out.vwv, VWV(8), t);
123         SSVAL(req->out.vwv, VWV(10), req->smb->negotiate.zone_offset/60);
124
125         /* Create a token value and add it to the outgoing packet. */
126         if (req->smb->negotiate.encrypted_passwords) {
127                 SSVAL(req->out.vwv, VWV(11), 8);
128                 get_challenge(req->smb, req->out.data);
129         }
130
131         req_send_reply(req);    
132 }
133
134 /****************************************************************************
135  Reply for the lanman 2.0 protocol.
136 ****************************************************************************/
137 static void reply_lanman2(struct request_context *req, uint16_t choice)
138 {
139         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
140         int secword=0;
141         time_t t = req->request_time.tv_sec;
142
143         req->smb->negotiate.encrypted_passwords = lp_encrypted_passwords();
144   
145         if (lp_security() != SEC_SHARE)
146                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
147
148         if (req->smb->negotiate.encrypted_passwords)
149                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
150
151         req->smb->negotiate.protocol = PROTOCOL_LANMAN2;
152
153         req_setup_reply(req, 13, 0);
154
155         SSVAL(req->out.vwv, VWV(0), choice);
156         SSVAL(req->out.vwv, VWV(1), secword); 
157         SSVAL(req->out.vwv, VWV(2), req->smb->negotiate.max_recv);
158         SSVAL(req->out.vwv, VWV(3), lp_maxmux());
159         SSVAL(req->out.vwv, VWV(4), 1);
160         SSVAL(req->out.vwv, VWV(5), raw); 
161         SIVAL(req->out.vwv, VWV(6), req->smb->pid);
162         srv_push_dos_date(req->smb, req->out.vwv, VWV(8), t);
163         SSVAL(req->out.vwv, VWV(10), req->smb->negotiate.zone_offset/60);
164
165         /* Create a token value and add it to the outgoing packet. */
166         if (req->smb->negotiate.encrypted_passwords) {
167                 SSVAL(req->out.vwv, VWV(11), 8);
168                 req_grow_data(req, 8);
169                 get_challenge(req->smb, req->out.data);
170         }
171
172         req_push_str(req, NULL, lp_workgroup(), -1, STR_TERMINATE);
173
174         req_send_reply(req);
175 }
176
177
178 #if 0
179 /****************************************************************************
180  Generate the spnego negprot reply blob. Return the number of bytes used.
181 ****************************************************************************/
182 static DATA_BLOB negprot_spnego(struct server_context *smb)
183 {
184         DATA_BLOB blob;
185         uint8_t guid[16];
186         const char *OIDs_krb5[] = {OID_KERBEROS5,
187                                    OID_KERBEROS5_OLD,
188                                    OID_NTLMSSP,
189                                    NULL};
190         const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
191         char *principal;
192
193         smb->negotiate.spnego_negotiated = True;
194
195         memset(guid, 0, 16);
196         safe_strcpy((char *)guid, lp_netbios_name(), 16);
197         strlower((char *)guid);
198
199 #if 0
200         /* strangely enough, NT does not send the single OID NTLMSSP when
201            not a ADS member, it sends no OIDs at all
202
203            we can't do this until we teach our sesssion setup parser to know
204            about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)
205         */
206         if (lp_security() != SEC_ADS) {
207                 memcpy(p, guid, 16);
208                 return 16;
209         }
210 #endif
211         if (lp_security() != SEC_ADS) {
212                 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
213         } else {
214                 asprintf(&principal, "%s$@%s", guid, lp_realm());
215                 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
216                 free(principal);
217         }
218
219         return blob;
220 }
221 #endif
222
223 /****************************************************************************
224  Reply for the nt protocol.
225 ****************************************************************************/
226 static void reply_nt1(struct request_context *req, uint16_t choice)
227 {
228         /* dual names + lock_and_read + nt SMBs + remote API calls */
229         int capabilities;
230         int secword=0;
231         time_t t = req->request_time.tv_sec;
232         NTTIME nttime;
233         BOOL negotiate_spnego = False;
234
235         unix_to_nt_time(&nttime, t);
236
237         capabilities = 
238                 CAP_NT_FIND | CAP_LOCK_AND_READ | 
239                 CAP_LEVEL_II_OPLOCKS | CAP_NT_SMBS | CAP_RPC_REMOTE_APIS;
240
241         req->smb->negotiate.encrypted_passwords = 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 (req->smb->negotiate.encrypted_passwords && 
247             (lp_security() != SEC_SHARE) &&
248             lp_use_spnego() &&
249             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
250 /* REWRITE              negotiate_spnego = True; 
251                 capabilities |= CAP_EXTENDED_SECURITY;
252 */
253         }
254         
255         if (lp_unix_extensions()) {
256                 capabilities |= CAP_UNIX;
257         }
258         
259         if (lp_large_readwrite()) {
260                 capabilities |= CAP_LARGE_READX | CAP_LARGE_WRITEX | CAP_W2K_SMBS;
261         }
262         
263         capabilities |= CAP_LARGE_FILES;
264
265         if (lp_readraw() && lp_writeraw()) {
266                 capabilities |= CAP_RAW_MODE;
267         }
268         
269         /* allow for disabling unicode */
270         if (lp_unicode()) {
271                 capabilities |= CAP_UNICODE;
272         }
273
274         if (lp_nt_status_support()) {
275                 capabilities |= CAP_STATUS32;
276         }
277         
278         if (lp_host_msdfs()) {
279                 capabilities |= CAP_DFS;
280         }
281         
282         if (lp_security() != SEC_SHARE) {
283                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
284         }
285
286         if (req->smb->negotiate.encrypted_passwords) {
287                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
288         }
289
290         req->smb->signing.signing_state = lp_server_signing();
291
292         switch (req->smb->signing.signing_state) {
293         case SMB_SIGNING_OFF:
294                 break;
295         case SMB_SIGNING_SUPPORTED:
296                 secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
297                 break;
298         case SMB_SIGNING_REQUIRED:
299                 secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED |
300                         NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
301                 break;
302         }
303         
304         req->smb->negotiate.protocol = PROTOCOL_NT1;
305
306         req_setup_reply(req, 17, 0);
307         
308         SSVAL(req->out.vwv, VWV(0), choice);
309         SCVAL(req->out.vwv, VWV(1), secword);
310
311         /* notice the strange +1 on vwv here? That's because
312            this is the one and only SMB packet that is malformed in
313            the specification - all the command words after the secword
314            are offset by 1 byte */
315         SSVAL(req->out.vwv+1, VWV(1), lp_maxmux());
316         SSVAL(req->out.vwv+1, VWV(2), 1); /* num vcs */
317         SIVAL(req->out.vwv+1, VWV(3), req->smb->negotiate.max_recv);
318         SIVAL(req->out.vwv+1, VWV(5), 0x10000); /* raw size. full 64k */
319         SIVAL(req->out.vwv+1, VWV(7), req->smb->pid); /* session key */
320         SIVAL(req->out.vwv+1, VWV(9), capabilities);
321         push_nttime(req->out.vwv+1, VWV(11), nttime);
322         SSVALS(req->out.vwv+1,VWV(15), req->smb->negotiate.zone_offset/60);
323         
324         if (!negotiate_spnego) {
325                 /* Create a token value and add it to the outgoing packet. */
326                 if (req->smb->negotiate.encrypted_passwords) {
327                         req_grow_data(req, 8);
328                         /* note that we do not send a challenge at all if
329                            we are using plaintext */
330                         get_challenge(req->smb, req->out.ptr);
331                         req->out.ptr += 8;
332                         SCVAL(req->out.vwv+1, VWV(16), 8);
333                 }
334                 req_push_str(req, NULL, lp_workgroup(), -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
335                 req_push_str(req, NULL, lp_netbios_name(), -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
336                 DEBUG(3,("not using SPNEGO\n"));
337         } else {
338 #if 0
339                 DATA_BLOB blob = negprot_spnego(req->smb);
340
341                 req_grow_data(req, blob.length);
342                 memcpy(req->out.ptr, blob.data, blob.length);
343                 DEBUG(3,("using SPNEGO\n"));
344 #else
345                 exit_server(req->smb, "no SPNEGO please");
346 #endif
347         }
348         
349         req_send_reply_nosign(req);     
350 }
351
352 /* these are the protocol lists used for auto architecture detection:
353
354 WinNT 3.51:
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 Win95:
365 protocol [PC NETWORK PROGRAM 1.0]
366 protocol [XENIX CORE]
367 protocol [MICROSOFT NETWORKS 1.03]
368 protocol [LANMAN1.0]
369 protocol [Windows for Workgroups 3.1a]
370 protocol [LM1.2X002]
371 protocol [LANMAN2.1]
372 protocol [NT LM 0.12]
373
374 Win2K:
375 protocol [PC NETWORK PROGRAM 1.0]
376 protocol [LANMAN1.0]
377 protocol [Windows for Workgroups 3.1a]
378 protocol [LM1.2X002]
379 protocol [LANMAN2.1]
380 protocol [NT LM 0.12]
381
382 OS/2:
383 protocol [PC NETWORK PROGRAM 1.0]
384 protocol [XENIX CORE]
385 protocol [LANMAN1.0]
386 protocol [LM1.2X002]
387 protocol [LANMAN2.1]
388 */
389
390 /*
391   * Modified to recognize the architecture of the remote machine better.
392   *
393   * This appears to be the matrix of which protocol is used by which
394   * MS product.
395        Protocol                       WfWg    Win95   WinNT  Win2K  OS/2
396        PC NETWORK PROGRAM 1.0          1       1       1      1      1
397        XENIX CORE                                      2             2
398        MICROSOFT NETWORKS 3.0          2       2       
399        DOS LM1.2X002                   3       3       
400        MICROSOFT NETWORKS 1.03                         3
401        DOS LANMAN2.1                   4       4       
402        LANMAN1.0                                       4      2      3
403        Windows for Workgroups 3.1a     5       5       5      3
404        LM1.2X002                                       6      4      4
405        LANMAN2.1                                       7      5      5
406        NT LM 0.12                              6       8      6
407   *
408   *  tim@fsg.com 09/29/95
409   *  Win2K added by matty 17/7/99
410   */
411   
412 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
413 #define ARCH_WIN95    0x2
414 #define ARCH_WINNT    0x4
415 #define ARCH_WIN2K    0xC      /* Win2K is like NT */
416 #define ARCH_OS2      0x14     /* Again OS/2 is like NT */
417 #define ARCH_SAMBA    0x20
418  
419 #define ARCH_ALL      0x3F
420  
421 /* List of supported protocols, most desired first */
422 static const struct {
423         const char *proto_name;
424         const char *short_name;
425         void (*proto_reply_fn)(struct request_context *req, uint16_t choice);
426         int protocol_level;
427 } supported_protocols[] = {
428         {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
429         {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
430         {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
431         {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
432         {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
433         {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
434         {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
435         {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
436         {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
437         {NULL,NULL,NULL,0},
438 };
439
440 /****************************************************************************
441  Reply to a negprot.
442 ****************************************************************************/
443
444 void reply_negprot(struct request_context *req)
445 {
446         int Index=0;
447         int choice = -1;
448         int protocol;
449         char *p;
450         int arch = ARCH_ALL;
451
452         if (req->smb->negotiate.done_negprot) {
453                 exit_server(req->smb, "multiple negprot's are not permitted");
454         }
455         req->smb->negotiate.done_negprot = True;
456
457         p = req->in.data + 1;
458
459         while (p < req->in.data + req->in.data_size) { 
460                 Index++;
461                 DEBUG(3,("Requested protocol [%s]\n",p));
462                 if (strcmp(p,"Windows for Workgroups 3.1a") == 0)
463                         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
464                 else if (strcmp(p,"DOS LM1.2X002") == 0)
465                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
466                 else if (strcmp(p,"DOS LANMAN2.1") == 0)
467                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
468                 else if (strcmp(p,"NT LM 0.12") == 0)
469                         arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
470                 else if (strcmp(p,"LANMAN2.1") == 0)
471                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
472                 else if (strcmp(p,"LM1.2X002") == 0)
473                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
474                 else if (strcmp(p,"MICROSOFT NETWORKS 1.03") == 0)
475                         arch &= ARCH_WINNT;
476                 else if (strcmp(p,"XENIX CORE") == 0)
477                         arch &= ( ARCH_WINNT | ARCH_OS2 );
478                 else if (strcmp(p,"Samba") == 0) {
479                         arch = ARCH_SAMBA;
480                         break;
481                 }
482  
483                 p += strlen(p) + 2;
484         }
485     
486         switch (arch) {
487                 case ARCH_SAMBA:
488                         set_remote_arch(req->smb, RA_SAMBA);
489                         break;
490                 case ARCH_WFWG:
491                         set_remote_arch(req->smb, RA_WFWG);
492                         break;
493                 case ARCH_WIN95:
494                         set_remote_arch(req->smb, RA_WIN95);
495                         break;
496                 case ARCH_WINNT:
497                         if (req->flags2==FLAGS2_WIN2K_SIGNATURE)
498                                 set_remote_arch(req->smb, RA_WIN2K);
499                         else
500                                 set_remote_arch(req->smb, RA_WINNT);
501                         break;
502                 case ARCH_WIN2K:
503                         set_remote_arch(req->smb, RA_WIN2K);
504                         break;
505                 case ARCH_OS2:
506                         set_remote_arch(req->smb, RA_OS2);
507                         break;
508                 default:
509                         set_remote_arch(req->smb, RA_UNKNOWN);
510                 break;
511         }
512  
513         /* possibly reload - change of architecture */
514         reload_services(req->smb, True);      
515     
516         /* Check for protocols, most desirable first */
517         for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
518                 p = req->in.data+1;
519                 Index = 0;
520                 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
521                                 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
522                         while (p < (req->in.data + req->in.data_size)) { 
523                                 if (strequal(p,supported_protocols[protocol].proto_name))
524                                         choice = Index;
525                                 Index++;
526                                 p += strlen(p) + 2;
527                         }
528                 if(choice != -1)
529                         break;
530         }
531   
532         if(choice != -1) {
533                 sub_set_remote_proto(supported_protocols[protocol].short_name);
534                 reload_services(req->smb, True);
535                 supported_protocols[protocol].proto_reply_fn(req, choice);
536                 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
537         } else {
538                 DEBUG(0,("No protocol supported !\n"));
539         }
540   
541         DEBUG(5,("negprot index=%d\n", choice));
542 }