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