this fixes plaintext passwords with win2000
[mat/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 extern fstring global_myworkgroup;
26 extern fstring remote_machine;
27 BOOL global_encrypted_passwords_negotiated = False;
28 BOOL global_spnego_negotiated = False;
29 struct auth_context *negprot_global_auth_context = NULL;
30
31 static void get_challenge(char buff[8]) 
32 {
33         NTSTATUS nt_status;
34         const uint8 *cryptkey;
35
36         /* We might be called more than once, muliple negprots are premitted */
37         if (negprot_global_auth_context) {
38                 DEBUG(3, ("get challenge: is this a secondary negprot?  negprot_global_auth_context is non-NULL!\n"));
39                 (negprot_global_auth_context->free)(&negprot_global_auth_context);
40         }
41
42         DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
43         if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) {
44                 DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status)));
45                 smb_panic("cannot make_negprot_global_auth_context!\n");
46         }
47         DEBUG(10, ("get challenge: getting challenge\n"));
48         cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context);
49         memcpy(buff, cryptkey, 8);
50 }
51
52 /****************************************************************************
53  Reply for the core protocol.
54 ****************************************************************************/
55
56 static int reply_corep(char *inbuf, char *outbuf)
57 {
58         int outsize = set_message(outbuf,1,0,True);
59
60         Protocol = PROTOCOL_CORE;
61         
62         return outsize;
63 }
64
65 /****************************************************************************
66  Reply for the coreplus protocol.
67 ****************************************************************************/
68
69 static int reply_coreplus(char *inbuf, char *outbuf)
70 {
71         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
72         int outsize = set_message(outbuf,13,0,True);
73         SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
74                         readbraw and writebraw (possibly) */
75         /* Reply, SMBlockread, SMBwritelock supported. */
76         SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
77         SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */    
78
79         Protocol = PROTOCOL_COREPLUS;
80
81         return outsize;
82 }
83
84 /****************************************************************************
85  Reply for the lanman 1.0 protocol.
86 ****************************************************************************/
87
88 static int reply_lanman1(char *inbuf, char *outbuf)
89 {
90         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
91         int secword=0;
92         time_t t = time(NULL);
93
94         global_encrypted_passwords_negotiated = lp_encrypted_passwords();
95
96         if (lp_security()>=SEC_USER)
97                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
98         if (global_encrypted_passwords_negotiated)
99                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
100
101         set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
102         SSVAL(outbuf,smb_vwv1,secword); 
103         /* Create a token value and add it to the outgoing packet. */
104         if (global_encrypted_passwords_negotiated) {
105                 get_challenge(smb_buf(outbuf));
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         }
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         extern pstring global_myname;
173         uint8 guid[16];
174         const char *OIDs_krb5[] = {OID_NTLMSSP,
175                                    OID_KERBEROS5,
176                                    OID_KERBEROS5_OLD,
177                                    NULL};
178         const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
179         char *principal;
180         int len;
181
182         global_spnego_negotiated = True;
183
184         memset(guid, 0, 16);
185         safe_strcpy((char *)guid, global_myname, 16);
186         strlower((char *)guid);
187
188 #if 0
189         /* strangely enough, NT does not sent the single OID NTLMSSP when
190            not a ADS member, it sends no OIDs at all
191
192            we can't do this until we teach our sesssion setup parser to know
193            about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)
194         */
195         if (lp_security() != SEC_ADS) {
196                 memcpy(p, guid, 16);
197                 return 16;
198         }
199 #endif
200         if (lp_security() != SEC_ADS) {
201                 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
202         } else {
203                 ADS_STRUCT *ads;
204                 ads = ads_init_simple();
205                 /* win2000 uses host$@REALM, which we will probably use eventually,
206                    but for now this works */
207                 asprintf(&principal, "HOST/%s@%s", guid, ads->realm);
208                 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
209                 free(principal);
210                 ads_destroy(&ads);
211         }
212         memcpy(p, blob.data, blob.length);
213         len = blob.length;
214         data_blob_free(&blob);
215         return len;
216 }
217
218 /****************************************************************************
219  Reply for the nt protocol.
220 ****************************************************************************/
221
222 static int reply_nt1(char *inbuf, char *outbuf)
223 {
224         /* dual names + lock_and_read + nt SMBs + remote API calls */
225         int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
226                 CAP_LEVEL_II_OPLOCKS;
227
228         int secword=0;
229         time_t t = time(NULL);
230         char *p, *q;
231         BOOL negotiate_spnego = False;
232
233         global_encrypted_passwords_negotiated = lp_encrypted_passwords();
234
235         /* do spnego in user level security if the client
236            supports it and we can do encrypted passwords */
237         
238         if (global_encrypted_passwords_negotiated && 
239             (lp_security() != SEC_SHARE) &&
240             lp_use_spnego() &&
241             (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
242                 negotiate_spnego = True;
243                 capabilities |= CAP_EXTENDED_SECURITY;
244         }
245         
246         capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNIX;
247         
248         if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
249                 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
250         
251         if (SMB_OFF_T_BITS == 64)
252                 capabilities |= CAP_LARGE_FILES;
253
254         if (lp_readraw() && lp_writeraw())
255                 capabilities |= CAP_RAW_MODE;
256         
257         /* allow for disabling unicode */
258         if (lp_unicode())
259                 capabilities |= CAP_UNICODE;
260
261         if (lp_nt_status_support())
262                 capabilities |= CAP_STATUS32;
263         
264         if (lp_host_msdfs())
265                 capabilities |= CAP_DFS;
266         
267         if (lp_security() >= SEC_USER)
268                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
269         if (global_encrypted_passwords_negotiated)
270                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
271         
272         set_message(outbuf,17,0,True);
273         
274         SCVAL(outbuf,smb_vwv1,secword);
275         
276         Protocol = PROTOCOL_NT1;
277         
278         SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
279         SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
280         SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
281         SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
282         SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
283         SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
284         put_long_date(outbuf+smb_vwv11+1,t);
285         SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
286         
287         p = q = smb_buf(outbuf);
288         if (!negotiate_spnego) {
289                 /* Create a token value and add it to the outgoing packet. */
290                 if (global_encrypted_passwords_negotiated) {
291                         /* note that we do not send a challenge at all if
292                            we are using plaintext */
293                         get_challenge(p);
294                         SSVALS(outbuf,smb_vwv16+1,8);
295                         p += 8;
296                 }
297                 p += srvstr_push(outbuf, p, global_myworkgroup, -1, 
298                                  STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
299                 DEBUG(3,("not using SPNEGO\n"));
300         } else {
301                 int len = negprot_spnego(p);
302                 
303                 SSVALS(outbuf,smb_vwv16+1,len);
304                 p += len;
305                 DEBUG(3,("using SPNEGO\n"));
306         }
307         
308         SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
309         set_message_end(outbuf, p);
310         
311         return (smb_len(outbuf)+4);
312 }
313
314 /* these are the protocol lists used for auto architecture detection:
315
316 WinNT 3.51:
317 protocol [PC NETWORK PROGRAM 1.0]
318 protocol [XENIX CORE]
319 protocol [MICROSOFT NETWORKS 1.03]
320 protocol [LANMAN1.0]
321 protocol [Windows for Workgroups 3.1a]
322 protocol [LM1.2X002]
323 protocol [LANMAN2.1]
324 protocol [NT LM 0.12]
325
326 Win95:
327 protocol [PC NETWORK PROGRAM 1.0]
328 protocol [XENIX CORE]
329 protocol [MICROSOFT NETWORKS 1.03]
330 protocol [LANMAN1.0]
331 protocol [Windows for Workgroups 3.1a]
332 protocol [LM1.2X002]
333 protocol [LANMAN2.1]
334 protocol [NT LM 0.12]
335
336 Win2K:
337 protocol [PC NETWORK PROGRAM 1.0]
338 protocol [LANMAN1.0]
339 protocol [Windows for Workgroups 3.1a]
340 protocol [LM1.2X002]
341 protocol [LANMAN2.1]
342 protocol [NT LM 0.12]
343
344 OS/2:
345 protocol [PC NETWORK PROGRAM 1.0]
346 protocol [XENIX CORE]
347 protocol [LANMAN1.0]
348 protocol [LM1.2X002]
349 protocol [LANMAN2.1]
350 */
351
352 /*
353   * Modified to recognize the architecture of the remote machine better.
354   *
355   * This appears to be the matrix of which protocol is used by which
356   * MS product.
357        Protocol                       WfWg    Win95   WinNT  Win2K  OS/2
358        PC NETWORK PROGRAM 1.0          1       1       1      1      1
359        XENIX CORE                                      2             2
360        MICROSOFT NETWORKS 3.0          2       2       
361        DOS LM1.2X002                   3       3       
362        MICROSOFT NETWORKS 1.03                         3
363        DOS LANMAN2.1                   4       4       
364        LANMAN1.0                                       4      2      3
365        Windows for Workgroups 3.1a     5       5       5      3
366        LM1.2X002                                       6      4      4
367        LANMAN2.1                                       7      5      5
368        NT LM 0.12                              6       8      6
369   *
370   *  tim@fsg.com 09/29/95
371   *  Win2K added by matty 17/7/99
372   */
373   
374 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
375 #define ARCH_WIN95    0x2
376 #define ARCH_WINNT    0x4
377 #define ARCH_WIN2K    0xC      /* Win2K is like NT */
378 #define ARCH_OS2      0x14     /* Again OS/2 is like NT */
379 #define ARCH_SAMBA    0x20
380  
381 #define ARCH_ALL      0x3F
382  
383 /* List of supported protocols, most desired first */
384 static struct {
385         char *proto_name;
386         char *short_name;
387         int (*proto_reply_fn)(char *, char *);
388         int protocol_level;
389 } supported_protocols[] = {
390         {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
391         {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
392         {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
393         {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
394         {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
395         {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
396         {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
397         {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
398         {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
399         {NULL,NULL,NULL,0},
400 };
401
402 /****************************************************************************
403  Reply to a negprot.
404 ****************************************************************************/
405
406 int reply_negprot(connection_struct *conn, 
407                   char *inbuf,char *outbuf, int dum_size, 
408                   int dum_buffsize)
409 {
410         int outsize = set_message(outbuf,1,0,True);
411         int Index=0;
412         int choice= -1;
413         int protocol;
414         char *p;
415         int bcc = SVAL(smb_buf(inbuf),-2);
416         int arch = ARCH_ALL;
417
418         static BOOL done_negprot = False;
419
420         START_PROFILE(SMBnegprot);
421
422         if (done_negprot) {
423                 END_PROFILE(SMBnegprot);
424                 exit_server("multiple negprot's are not permitted");
425         }
426         done_negprot = True;
427
428         p = smb_buf(inbuf)+1;
429         while (p < (smb_buf(inbuf) + bcc)) { 
430                 Index++;
431                 DEBUG(3,("Requested protocol [%s]\n",p));
432                 if (strcsequal(p,"Windows for Workgroups 3.1a"))
433                         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
434                 else if (strcsequal(p,"DOS LM1.2X002"))
435                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
436                 else if (strcsequal(p,"DOS LANMAN2.1"))
437                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
438                 else if (strcsequal(p,"NT LM 0.12"))
439                         arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
440                 else if (strcsequal(p,"LANMAN2.1"))
441                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
442                 else if (strcsequal(p,"LM1.2X002"))
443                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
444                 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
445                         arch &= ARCH_WINNT;
446                 else if (strcsequal(p,"XENIX CORE"))
447                         arch &= ( ARCH_WINNT | ARCH_OS2 );
448                 else if (strcsequal(p,"Samba")) {
449                         arch = ARCH_SAMBA;
450                         break;
451                 }
452  
453                 p += strlen(p) + 2;
454         }
455     
456         switch ( arch ) {
457                 case ARCH_SAMBA:
458                         set_remote_arch(RA_SAMBA);
459                         break;
460                 case ARCH_WFWG:
461                         set_remote_arch(RA_WFWG);
462                         break;
463                 case ARCH_WIN95:
464                         set_remote_arch(RA_WIN95);
465                         break;
466                 case ARCH_WINNT:
467                         if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
468                                 set_remote_arch(RA_WIN2K);
469                         else
470                                 set_remote_arch(RA_WINNT);
471                         break;
472                 case ARCH_WIN2K:
473                         set_remote_arch(RA_WIN2K);
474                         break;
475                 case ARCH_OS2:
476                         set_remote_arch(RA_OS2);
477                         break;
478                 default:
479                         set_remote_arch(RA_UNKNOWN);
480                 break;
481         }
482  
483         /* possibly reload - change of architecture */
484         reload_services(True);      
485     
486         /* Check for protocols, most desirable first */
487         for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
488                 p = smb_buf(inbuf)+1;
489                 Index = 0;
490                 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
491                                 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
492                         while (p < (smb_buf(inbuf) + bcc)) { 
493                                 if (strequal(p,supported_protocols[protocol].proto_name))
494                                         choice = Index;
495                                 Index++;
496                                 p += strlen(p) + 2;
497                         }
498                 if(choice != -1)
499                         break;
500         }
501   
502         SSVAL(outbuf,smb_vwv0,choice);
503         if(choice != -1) {
504                 extern fstring remote_proto;
505                 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
506                 reload_services(True);          
507                 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
508                 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
509         } else {
510                 DEBUG(0,("No protocol supported !\n"));
511         }
512         SSVAL(outbuf,smb_vwv0,choice);
513   
514         DEBUG( 5, ( "negprot index=%d\n", choice ) );
515
516         END_PROFILE(SMBnegprot);
517         return(outsize);
518 }