challange -> challenge
[kai/samba.git] / source3 / smbd / negprot.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    negprot reply code
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23
24 extern int Protocol;
25 extern int max_recv;
26 extern fstring global_myworkgroup;
27 extern fstring remote_machine;
28 BOOL global_encrypted_passwords_negotiated = False;
29 BOOL global_spnego_negotiated = False;
30 auth_authsupplied_info *negprot_global_auth_info = NULL;
31
32 /****************************************************************************
33 reply for the core protocol
34 ****************************************************************************/
35 static int reply_corep(char *inbuf, char *outbuf)
36 {
37         int outsize = set_message(outbuf,1,0,True);
38
39         Protocol = PROTOCOL_CORE;
40         
41         return outsize;
42 }
43
44
45 /****************************************************************************
46 reply for the coreplus protocol
47 ****************************************************************************/
48 static int reply_coreplus(char *inbuf, char *outbuf)
49 {
50   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
51   int outsize = set_message(outbuf,13,0,True);
52   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
53                                  readbraw and writebraw (possibly) */
54   /* Reply, SMBlockread, SMBwritelock supported. */
55   SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
56   SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */  
57
58   Protocol = PROTOCOL_COREPLUS;
59
60   return outsize;
61 }
62
63
64 /****************************************************************************
65 reply for the lanman 1.0 protocol
66 ****************************************************************************/
67 static int reply_lanman1(char *inbuf, char *outbuf)
68 {
69   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
70   int secword=0;
71   time_t t = time(NULL);
72   DATA_BLOB cryptkey;
73
74   global_encrypted_passwords_negotiated = lp_encrypted_passwords();
75
76   if (lp_security()>=SEC_USER) secword |= 1;
77   if (global_encrypted_passwords_negotiated) secword |= 2;
78
79   set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
80   SSVAL(outbuf,smb_vwv1,secword); 
81   /* Create a token value and add it to the outgoing packet. */
82   if (global_encrypted_passwords_negotiated) {
83           if (!make_auth_info_subsystem(&negprot_global_auth_info)) {
84                   smb_panic("cannot make_negprot_global_auth_info!\n");
85           }
86           cryptkey = auth_get_challenge(negprot_global_auth_info);
87           memcpy(smb_buf(outbuf), cryptkey.data, 8);
88           data_blob_free(&cryptkey);
89   }
90
91   Protocol = PROTOCOL_LANMAN1;
92
93   /* Reply, SMBlockread, SMBwritelock supported. */
94   SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
95   SSVAL(outbuf,smb_vwv2,max_recv);
96   SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
97   SSVAL(outbuf,smb_vwv4,1);
98   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
99                                  readbraw writebraw (possibly) */
100   SIVAL(outbuf,smb_vwv6,sys_getpid());
101   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
102
103   put_dos_date(outbuf,smb_vwv8,t);
104
105   return (smb_len(outbuf)+4);
106 }
107
108
109 /****************************************************************************
110 reply for the lanman 2.0 protocol
111 ****************************************************************************/
112 static int reply_lanman2(char *inbuf, char *outbuf)
113 {
114   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
115   int secword=0;
116   time_t t = time(NULL);
117   DATA_BLOB cryptkey;
118
119   global_encrypted_passwords_negotiated = lp_encrypted_passwords();
120   
121   if (lp_security()>=SEC_USER) secword |= 1;
122   if (global_encrypted_passwords_negotiated) secword |= 2;
123
124   set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
125   SSVAL(outbuf,smb_vwv1,secword); 
126   SIVAL(outbuf,smb_vwv6,sys_getpid());
127
128   if (global_encrypted_passwords_negotiated) {
129           if (!make_auth_info_subsystem(&negprot_global_auth_info)) {
130                   smb_panic("cannot make_negprot_global_auth_info!\n");
131           }
132           cryptkey = auth_get_challenge(negprot_global_auth_info);
133           memcpy(smb_buf(outbuf), cryptkey.data, 8);
134           data_blob_free(&cryptkey);
135   }
136
137   Protocol = PROTOCOL_LANMAN2;
138
139   /* Reply, SMBlockread, SMBwritelock supported. */
140   SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
141   SSVAL(outbuf,smb_vwv2,max_recv);
142   SSVAL(outbuf,smb_vwv3,lp_maxmux()); 
143   SSVAL(outbuf,smb_vwv4,1);
144   SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
145   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
146   put_dos_date(outbuf,smb_vwv8,t);
147
148   return (smb_len(outbuf)+4);
149 }
150
151
152
153 /* 
154    generate the spnego negprot reply blob. Return the number of bytes used
155 */
156 static int negprot_spnego(char *p)
157 {
158         DATA_BLOB blob;
159         extern pstring global_myname;
160         uint8 guid[16];
161         const char *OIDs[] = {OID_NTLMSSP,
162                               OID_KERBEROS5,
163                               OID_KERBEROS5_OLD,
164                               NULL};
165         char *principal;
166         int len;
167
168         global_spnego_negotiated = True;
169
170         memset(guid, 0, 16);
171         safe_strcpy((char *)guid, global_myname, 16);
172         strlower((char *)guid);
173
174         /* strangely enough, NT does not sent the single OID NTLMSSP when
175            not a ADS member, it sends no OIDs at all */
176         if (lp_security() != SEC_ADS) {
177                 memcpy(p, guid, 16);
178                 return 16;
179         }
180
181         /* win2000 uses host$@REALM, which we will probably use eventually,
182            but for now this works */
183         asprintf(&principal, "HOST/%s@%s", guid, lp_realm());
184         blob = spnego_gen_negTokenInit(guid, OIDs, principal);
185         free(principal);
186
187         memcpy(p, blob.data, blob.length);
188         len = blob.length;
189         data_blob_free(&blob);
190         return len;
191 }
192
193                 
194
195 /****************************************************************************
196 reply for the nt protocol
197 ****************************************************************************/
198 static int reply_nt1(char *inbuf, char *outbuf)
199 {
200         /* dual names + lock_and_read + nt SMBs + remote API calls */
201         int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
202                 CAP_LEVEL_II_OPLOCKS|CAP_STATUS32;
203
204         int secword=0;
205         time_t t = time(NULL);
206         DATA_BLOB cryptkey;
207         char *p, *q;
208         BOOL negotiate_spnego = False;
209
210         global_encrypted_passwords_negotiated = lp_encrypted_passwords();
211
212         /* do spnego in user level security if the client
213            supports it and we can do encrypted passwords */
214         
215         if (global_encrypted_passwords_negotiated && 
216             (lp_security() != SEC_SHARE) &&
217             (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
218                 negotiate_spnego = True;
219                 capabilities |= CAP_EXTENDED_SECURITY;
220         }
221         
222         capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
223         
224         if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64)) {
225                 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
226         }
227         
228         if (SMB_OFF_T_BITS == 64) {
229                 capabilities |= CAP_LARGE_FILES;
230         }
231         
232         if (lp_readraw() && lp_writeraw()) {
233                 capabilities |= CAP_RAW_MODE;
234         }
235         
236         /* allow for disabling unicode */
237         if (lp_unicode()) {
238                 capabilities |= CAP_UNICODE;
239         }
240         
241         if (lp_host_msdfs())
242                 capabilities |= CAP_DFS;
243         
244         if (lp_security() >= SEC_USER) secword |= 1;
245         if (global_encrypted_passwords_negotiated) secword |= 2;
246         
247         set_message(outbuf,17,0,True);
248         
249         CVAL(outbuf,smb_vwv1) = secword;
250         
251         Protocol = PROTOCOL_NT1;
252         
253         SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
254         SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
255         SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
256         SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
257         SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
258         SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
259         put_long_date(outbuf+smb_vwv11+1,t);
260         SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
261         
262         p = q = smb_buf(outbuf);
263         if (!negotiate_spnego) {
264                 if (global_encrypted_passwords_negotiated) { 
265                         if (!make_auth_info_subsystem(&negprot_global_auth_info)) {
266                                 smb_panic("cannot make_negprot_global_auth_info!\n");
267                         }
268                         cryptkey = auth_get_challenge(negprot_global_auth_info);
269                         memcpy(p, cryptkey.data, 8);
270                         data_blob_free(&cryptkey);
271                 }
272                 SSVALS(outbuf,smb_vwv16+1,8);
273                 p += 8;
274                 p += srvstr_push(outbuf, p, global_myworkgroup, -1, 
275                                  STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
276                 DEBUG(3,("not using SPNEGO\n"));
277         } else {
278                 int len = negprot_spnego(p);
279                 
280                 SSVALS(outbuf,smb_vwv16+1,len);
281                 p += len;
282                 DEBUG(3,("using SPNEGO\n"));
283         }
284         
285         SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
286         set_message_end(outbuf, p);
287         
288         return (smb_len(outbuf)+4);
289 }
290
291 /* these are the protocol lists used for auto architecture detection:
292
293 WinNT 3.51:
294 protocol [PC NETWORK PROGRAM 1.0]
295 protocol [XENIX CORE]
296 protocol [MICROSOFT NETWORKS 1.03]
297 protocol [LANMAN1.0]
298 protocol [Windows for Workgroups 3.1a]
299 protocol [LM1.2X002]
300 protocol [LANMAN2.1]
301 protocol [NT LM 0.12]
302
303 Win95:
304 protocol [PC NETWORK PROGRAM 1.0]
305 protocol [XENIX CORE]
306 protocol [MICROSOFT NETWORKS 1.03]
307 protocol [LANMAN1.0]
308 protocol [Windows for Workgroups 3.1a]
309 protocol [LM1.2X002]
310 protocol [LANMAN2.1]
311 protocol [NT LM 0.12]
312
313 Win2K:
314 protocol [PC NETWORK PROGRAM 1.0]
315 protocol [LANMAN1.0]
316 protocol [Windows for Workgroups 3.1a]
317 protocol [LM1.2X002]
318 protocol [LANMAN2.1]
319 protocol [NT LM 0.12]
320
321 OS/2:
322 protocol [PC NETWORK PROGRAM 1.0]
323 protocol [XENIX CORE]
324 protocol [LANMAN1.0]
325 protocol [LM1.2X002]
326 protocol [LANMAN2.1]
327 */
328
329 /*
330   * Modified to recognize the architecture of the remote machine better.
331   *
332   * This appears to be the matrix of which protocol is used by which
333   * MS product.
334        Protocol                       WfWg    Win95   WinNT  Win2K  OS/2
335        PC NETWORK PROGRAM 1.0          1       1       1      1      1
336        XENIX CORE                                      2             2
337        MICROSOFT NETWORKS 3.0          2       2       
338        DOS LM1.2X002                   3       3       
339        MICROSOFT NETWORKS 1.03                         3
340        DOS LANMAN2.1                   4       4       
341        LANMAN1.0                                       4      2      3
342        Windows for Workgroups 3.1a     5       5       5      3
343        LM1.2X002                                       6      4      4
344        LANMAN2.1                                       7      5      5
345        NT LM 0.12                              6       8      6
346   *
347   *  tim@fsg.com 09/29/95
348   *  Win2K added by matty 17/7/99
349   */
350   
351 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
352 #define ARCH_WIN95    0x2
353 #define ARCH_WINNT    0x4
354 #define ARCH_WIN2K    0xC      /* Win2K is like NT */
355 #define ARCH_OS2      0x14     /* Again OS/2 is like NT */
356 #define ARCH_SAMBA    0x20
357  
358 #define ARCH_ALL      0x3F
359  
360 /* List of supported protocols, most desired first */
361 static struct {
362   char *proto_name;
363   char *short_name;
364   int (*proto_reply_fn)(char *, char *);
365   int protocol_level;
366 } supported_protocols[] = {
367   {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
368   {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
369   {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
370   {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
371   {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
372   {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
373   {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
374   {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
375   {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
376   {NULL,NULL,NULL,0},
377 };
378
379
380 /****************************************************************************
381   reply to a negprot
382 ****************************************************************************/
383 int reply_negprot(connection_struct *conn, 
384                   char *inbuf,char *outbuf, int dum_size, 
385                   int dum_buffsize)
386 {
387   int outsize = set_message(outbuf,1,0,True);
388   int Index=0;
389   int choice= -1;
390   int protocol;
391   char *p;
392   int bcc = SVAL(smb_buf(inbuf),-2);
393   int arch = ARCH_ALL;
394   START_PROFILE(SMBnegprot);
395
396   p = smb_buf(inbuf)+1;
397   while (p < (smb_buf(inbuf) + bcc))
398     { 
399       Index++;
400       DEBUG(3,("Requested protocol [%s]\n",p));
401       if (strcsequal(p,"Windows for Workgroups 3.1a"))
402         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
403       else if (strcsequal(p,"DOS LM1.2X002"))
404         arch &= ( ARCH_WFWG | ARCH_WIN95 );
405       else if (strcsequal(p,"DOS LANMAN2.1"))
406         arch &= ( ARCH_WFWG | ARCH_WIN95 );
407       else if (strcsequal(p,"NT LM 0.12"))
408         arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
409       else if (strcsequal(p,"LANMAN2.1"))
410         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
411       else if (strcsequal(p,"LM1.2X002"))
412         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
413       else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
414         arch &= ARCH_WINNT;
415       else if (strcsequal(p,"XENIX CORE"))
416         arch &= ( ARCH_WINNT | ARCH_OS2 );
417       else if (strcsequal(p,"Samba")) {
418         arch = ARCH_SAMBA;
419         break;
420       }
421  
422       p += strlen(p) + 2;
423     }
424     
425   switch ( arch ) {
426   case ARCH_SAMBA:
427     set_remote_arch(RA_SAMBA);
428     break;
429   case ARCH_WFWG:
430     set_remote_arch(RA_WFWG);
431     break;
432   case ARCH_WIN95:
433     set_remote_arch(RA_WIN95);
434     break;
435   case ARCH_WINNT:
436    if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
437      set_remote_arch(RA_WIN2K);
438    else
439      set_remote_arch(RA_WINNT);
440     break;
441   case ARCH_WIN2K:
442     set_remote_arch(RA_WIN2K);
443     break;
444   case ARCH_OS2:
445     set_remote_arch(RA_OS2);
446     break;
447   default:
448     set_remote_arch(RA_UNKNOWN);
449     break;
450   }
451  
452   /* possibly reload - change of architecture */
453   reload_services(True);      
454     
455   /* Check for protocols, most desirable first */
456   for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
457     {
458       p = smb_buf(inbuf)+1;
459       Index = 0;
460       if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
461           (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
462         while (p < (smb_buf(inbuf) + bcc))
463           { 
464             if (strequal(p,supported_protocols[protocol].proto_name))
465               choice = Index;
466             Index++;
467             p += strlen(p) + 2;
468           }
469       if(choice != -1)
470         break;
471     }
472   
473   SSVAL(outbuf,smb_vwv0,choice);
474   if(choice != -1) {
475     extern fstring remote_proto;
476     fstrcpy(remote_proto,supported_protocols[protocol].short_name);
477     reload_services(True);          
478     outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
479     DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
480   }
481   else {
482     DEBUG(0,("No protocol supported !\n"));
483   }
484   SSVAL(outbuf,smb_vwv0,choice);
485   
486   DEBUG( 5, ( "negprot index=%d\n", choice ) );
487
488   END_PROFILE(SMBnegprot);
489   return(outsize);
490 }
491