This is another rather major change to the samba authenticaion
[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_challange(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_challange(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         /* win2000 uses host$@REALM, which we will probably use eventually,
175            but for now this works */
176         asprintf(&principal, "HOST/%s@%s", guid, lp_realm());
177         blob = spnego_gen_negTokenInit(guid, OIDs, principal);
178         free(principal);
179
180         memcpy(p, blob.data, blob.length);
181         len = blob.length;
182         data_blob_free(&blob);
183         return len;
184 }
185
186                 
187
188 /****************************************************************************
189 reply for the nt protocol
190 ****************************************************************************/
191 static int reply_nt1(char *inbuf, char *outbuf)
192 {
193         /* dual names + lock_and_read + nt SMBs + remote API calls */
194         int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
195                 CAP_LEVEL_II_OPLOCKS|CAP_STATUS32;
196
197         int secword=0;
198         time_t t = time(NULL);
199         DATA_BLOB cryptkey;
200         char *p, *q;
201         BOOL negotiate_spnego = False;
202
203         global_encrypted_passwords_negotiated = lp_encrypted_passwords();
204
205         /* do spnego in user level security if the client
206            supports it and we can do encrypted passwords */
207         
208         if (global_encrypted_passwords_negotiated && 
209             (lp_security() != SEC_SHARE) &&
210             (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
211                 negotiate_spnego = True;
212                 capabilities |= CAP_EXTENDED_SECURITY;
213         }
214         
215         capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
216         
217         if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64)) {
218                 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
219         }
220         
221         if (SMB_OFF_T_BITS == 64) {
222                 capabilities |= CAP_LARGE_FILES;
223         }
224         
225         if (lp_readraw() && lp_writeraw()) {
226                 capabilities |= CAP_RAW_MODE;
227         }
228         
229         /* allow for disabling unicode */
230         if (lp_unicode()) {
231                 capabilities |= CAP_UNICODE;
232         }
233         
234         if (lp_host_msdfs())
235                 capabilities |= CAP_DFS;
236         
237         if (lp_security() >= SEC_USER) secword |= 1;
238         if (global_encrypted_passwords_negotiated) secword |= 2;
239         
240         set_message(outbuf,17,0,True);
241         
242         CVAL(outbuf,smb_vwv1) = secword;
243         
244         Protocol = PROTOCOL_NT1;
245         
246         SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
247         SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
248         SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
249         SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
250         SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
251         SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
252         put_long_date(outbuf+smb_vwv11+1,t);
253         SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
254         
255         p = q = smb_buf(outbuf);
256         if (!negotiate_spnego) {
257                 if (global_encrypted_passwords_negotiated) { 
258                         if (!make_auth_info_subsystem(&negprot_global_auth_info)) {
259                                 smb_panic("cannot make_negprot_global_auth_info!\n");
260                         }
261                         cryptkey = auth_get_challange(negprot_global_auth_info);
262                         memcpy(p, cryptkey.data, 8);
263                         data_blob_free(&cryptkey);
264                 }
265                 SSVALS(outbuf,smb_vwv16+1,8);
266                 p += 8;
267                 DEBUG(3,("not using SPNEGO\n"));
268         } else {
269                 int len = negprot_spnego(p);
270                 
271                 SSVALS(outbuf,smb_vwv16+1,len);
272                 p += len;
273                 DEBUG(3,("using SPNEGO\n"));
274         }
275         p += srvstr_push(outbuf, p, global_myworkgroup, -1, 
276                          STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
277         
278         SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
279         set_message_end(outbuf, p);
280         
281         return (smb_len(outbuf)+4);
282 }
283
284 /* these are the protocol lists used for auto architecture detection:
285
286 WinNT 3.51:
287 protocol [PC NETWORK PROGRAM 1.0]
288 protocol [XENIX CORE]
289 protocol [MICROSOFT NETWORKS 1.03]
290 protocol [LANMAN1.0]
291 protocol [Windows for Workgroups 3.1a]
292 protocol [LM1.2X002]
293 protocol [LANMAN2.1]
294 protocol [NT LM 0.12]
295
296 Win95:
297 protocol [PC NETWORK PROGRAM 1.0]
298 protocol [XENIX CORE]
299 protocol [MICROSOFT NETWORKS 1.03]
300 protocol [LANMAN1.0]
301 protocol [Windows for Workgroups 3.1a]
302 protocol [LM1.2X002]
303 protocol [LANMAN2.1]
304 protocol [NT LM 0.12]
305
306 Win2K:
307 protocol [PC NETWORK PROGRAM 1.0]
308 protocol [LANMAN1.0]
309 protocol [Windows for Workgroups 3.1a]
310 protocol [LM1.2X002]
311 protocol [LANMAN2.1]
312 protocol [NT LM 0.12]
313
314 OS/2:
315 protocol [PC NETWORK PROGRAM 1.0]
316 protocol [XENIX CORE]
317 protocol [LANMAN1.0]
318 protocol [LM1.2X002]
319 protocol [LANMAN2.1]
320 */
321
322 /*
323   * Modified to recognize the architecture of the remote machine better.
324   *
325   * This appears to be the matrix of which protocol is used by which
326   * MS product.
327        Protocol                       WfWg    Win95   WinNT  Win2K  OS/2
328        PC NETWORK PROGRAM 1.0          1       1       1      1      1
329        XENIX CORE                                      2             2
330        MICROSOFT NETWORKS 3.0          2       2       
331        DOS LM1.2X002                   3       3       
332        MICROSOFT NETWORKS 1.03                         3
333        DOS LANMAN2.1                   4       4       
334        LANMAN1.0                                       4      2      3
335        Windows for Workgroups 3.1a     5       5       5      3
336        LM1.2X002                                       6      4      4
337        LANMAN2.1                                       7      5      5
338        NT LM 0.12                              6       8      6
339   *
340   *  tim@fsg.com 09/29/95
341   *  Win2K added by matty 17/7/99
342   */
343   
344 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
345 #define ARCH_WIN95    0x2
346 #define ARCH_WINNT    0x4
347 #define ARCH_WIN2K    0xC      /* Win2K is like NT */
348 #define ARCH_OS2      0x14     /* Again OS/2 is like NT */
349 #define ARCH_SAMBA    0x20
350  
351 #define ARCH_ALL      0x3F
352  
353 /* List of supported protocols, most desired first */
354 static struct {
355   char *proto_name;
356   char *short_name;
357   int (*proto_reply_fn)(char *, char *);
358   int protocol_level;
359 } supported_protocols[] = {
360   {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
361   {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
362   {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
363   {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
364   {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
365   {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
366   {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
367   {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
368   {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
369   {NULL,NULL,NULL,0},
370 };
371
372
373 /****************************************************************************
374   reply to a negprot
375 ****************************************************************************/
376 int reply_negprot(connection_struct *conn, 
377                   char *inbuf,char *outbuf, int dum_size, 
378                   int dum_buffsize)
379 {
380   int outsize = set_message(outbuf,1,0,True);
381   int Index=0;
382   int choice= -1;
383   int protocol;
384   char *p;
385   int bcc = SVAL(smb_buf(inbuf),-2);
386   int arch = ARCH_ALL;
387   START_PROFILE(SMBnegprot);
388
389   p = smb_buf(inbuf)+1;
390   while (p < (smb_buf(inbuf) + bcc))
391     { 
392       Index++;
393       DEBUG(3,("Requested protocol [%s]\n",p));
394       if (strcsequal(p,"Windows for Workgroups 3.1a"))
395         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
396       else if (strcsequal(p,"DOS LM1.2X002"))
397         arch &= ( ARCH_WFWG | ARCH_WIN95 );
398       else if (strcsequal(p,"DOS LANMAN2.1"))
399         arch &= ( ARCH_WFWG | ARCH_WIN95 );
400       else if (strcsequal(p,"NT LM 0.12"))
401         arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
402       else if (strcsequal(p,"LANMAN2.1"))
403         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
404       else if (strcsequal(p,"LM1.2X002"))
405         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
406       else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
407         arch &= ARCH_WINNT;
408       else if (strcsequal(p,"XENIX CORE"))
409         arch &= ( ARCH_WINNT | ARCH_OS2 );
410       else if (strcsequal(p,"Samba")) {
411         arch = ARCH_SAMBA;
412         break;
413       }
414  
415       p += strlen(p) + 2;
416     }
417     
418   switch ( arch ) {
419   case ARCH_SAMBA:
420     set_remote_arch(RA_SAMBA);
421     break;
422   case ARCH_WFWG:
423     set_remote_arch(RA_WFWG);
424     break;
425   case ARCH_WIN95:
426     set_remote_arch(RA_WIN95);
427     break;
428   case ARCH_WINNT:
429    if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
430      set_remote_arch(RA_WIN2K);
431    else
432      set_remote_arch(RA_WINNT);
433     break;
434   case ARCH_WIN2K:
435     set_remote_arch(RA_WIN2K);
436     break;
437   case ARCH_OS2:
438     set_remote_arch(RA_OS2);
439     break;
440   default:
441     set_remote_arch(RA_UNKNOWN);
442     break;
443   }
444  
445   /* possibly reload - change of architecture */
446   reload_services(True);      
447     
448   /* Check for protocols, most desirable first */
449   for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
450     {
451       p = smb_buf(inbuf)+1;
452       Index = 0;
453       if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
454           (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
455         while (p < (smb_buf(inbuf) + bcc))
456           { 
457             if (strequal(p,supported_protocols[protocol].proto_name))
458               choice = Index;
459             Index++;
460             p += strlen(p) + 2;
461           }
462       if(choice != -1)
463         break;
464     }
465   
466   SSVAL(outbuf,smb_vwv0,choice);
467   if(choice != -1) {
468     extern fstring remote_proto;
469     fstrcpy(remote_proto,supported_protocols[protocol].short_name);
470     reload_services(True);          
471     outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
472     DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
473   }
474   else {
475     DEBUG(0,("No protocol supported !\n"));
476   }
477   SSVAL(outbuf,smb_vwv0,choice);
478   
479   DEBUG( 5, ( "negprot index=%d\n", choice ) );
480
481   END_PROFILE(SMBnegprot);
482   return(outsize);
483 }
484