possible bug in change oem password code: replaced E_P16 and E_md4hash
[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 DEBUGLEVEL;
25 extern int Protocol;
26 extern int max_recv;
27 extern fstring global_myworkgroup;
28 extern fstring remote_machine;
29 extern pstring myhostname;
30
31 /****************************************************************************
32 reply for the core protocol
33 ****************************************************************************/
34 static int reply_corep(char *outbuf)
35 {
36         int outsize = set_message(outbuf,1,0,True);
37
38         Protocol = PROTOCOL_CORE;
39         
40         return outsize;
41 }
42
43
44 /****************************************************************************
45 reply for the coreplus protocol
46 ****************************************************************************/
47 static int reply_coreplus(char *outbuf)
48 {
49   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
50   int outsize = set_message(outbuf,13,0,True);
51   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
52                                  readbraw and writebraw (possibly) */
53   /* Reply, SMBlockread, SMBwritelock supported. */
54   SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
55   SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */  
56
57   Protocol = PROTOCOL_COREPLUS;
58
59   return outsize;
60 }
61
62
63 /****************************************************************************
64 reply for the lanman 1.0 protocol
65 ****************************************************************************/
66 static int reply_lanman1(char *outbuf)
67 {
68   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
69   int secword=0;
70   BOOL doencrypt = SMBENCRYPT();
71   time_t t = time(NULL);
72
73   if (lp_security()>=SEC_USER) secword |= 1;
74   if (doencrypt) secword |= 2;
75
76   set_message(outbuf,13,doencrypt?8:0,True);
77   SSVAL(outbuf,smb_vwv1,secword); 
78   /* Create a token value and add it to the outgoing packet. */
79   if (doencrypt) 
80     generate_next_challenge(smb_buf(outbuf));
81
82   Protocol = PROTOCOL_LANMAN1;
83
84   /* Reply, SMBlockread, SMBwritelock supported. */
85   SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
86   SSVAL(outbuf,smb_vwv2,max_recv);
87   SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
88   SSVAL(outbuf,smb_vwv4,1);
89   SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
90                                  readbraw writebraw (possibly) */
91   SIVAL(outbuf,smb_vwv6,getpid());
92   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
93
94   put_dos_date(outbuf,smb_vwv8,t);
95
96   return (smb_len(outbuf)+4);
97 }
98
99
100 /****************************************************************************
101 reply for the lanman 2.0 protocol
102 ****************************************************************************/
103 static int reply_lanman2(char *outbuf)
104 {
105   int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
106   int secword=0;
107   BOOL doencrypt = SMBENCRYPT();
108   time_t t = time(NULL);
109   struct cli_state *cli = NULL;
110   char cryptkey[8];
111   char crypt_len = 0;
112
113   if (lp_security() == SEC_SERVER) {
114           cli = server_cryptkey();
115   }
116
117   if (cli) {
118           DEBUG(3,("using password server validation\n"));
119           doencrypt = ((cli->sec_mode & 2) != 0);
120   }
121
122   if (lp_security()>=SEC_USER) secword |= 1;
123   if (doencrypt) secword |= 2;
124
125   if (doencrypt) {
126           crypt_len = 8;
127           if (!cli) {
128                   generate_next_challenge(cryptkey);
129           } else {
130                   memcpy(cryptkey, cli->cryptkey, 8);
131                   set_challenge(cli->cryptkey);
132           }
133   }
134
135   set_message(outbuf,13,crypt_len,True);
136   SSVAL(outbuf,smb_vwv1,secword); 
137   SIVAL(outbuf,smb_vwv6,getpid());
138   if (doencrypt) 
139           memcpy(smb_buf(outbuf), cryptkey, 8);
140
141   Protocol = PROTOCOL_LANMAN2;
142
143   /* Reply, SMBlockread, SMBwritelock supported. */
144   SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
145   SSVAL(outbuf,smb_vwv2,max_recv);
146   SSVAL(outbuf,smb_vwv3,lp_maxmux()); 
147   SSVAL(outbuf,smb_vwv4,1);
148   SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
149   SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
150   put_dos_date(outbuf,smb_vwv8,t);
151
152   return (smb_len(outbuf)+4);
153 }
154
155
156 /****************************************************************************
157 reply for the nt protocol
158 ****************************************************************************/
159 static int reply_nt1(char *outbuf)
160 {
161   /* dual names + lock_and_read + nt SMBs + remote API calls */
162   int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
163                      (lp_nt_smb_support() ? CAP_NT_SMBS | CAP_RPC_REMOTE_APIS : 0) |
164                      (SMB_OFF_T_BITS == 64 ? CAP_LARGE_FILES : 0);
165
166
167 /*
168   other valid capabilities which we may support at some time...
169                      CAP_LARGE_READX|CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
170  */
171
172   int secword=0;
173   BOOL doencrypt = SMBENCRYPT();
174   time_t t = time(NULL);
175   int data_len;
176   struct cli_state *cli = NULL;
177   char cryptkey[8];
178   char crypt_len = 0;
179
180   if (lp_security() == SEC_SERVER) {
181           cli = server_cryptkey();
182   }
183
184   if (cli) {
185           DEBUG(3,("using password server validation\n"));
186           doencrypt = ((cli->sec_mode & 2) != 0);
187   }
188
189   if (doencrypt) {
190           crypt_len = 8;
191           if (!cli) {
192                   generate_next_challenge(cryptkey);
193           } else {
194                   memcpy(cryptkey, cli->cryptkey, 8);
195                   set_challenge(cli->cryptkey);
196           }
197   }
198
199   if (lp_readraw() && lp_writeraw()) {
200           capabilities |= CAP_RAW_MODE;
201   }
202
203   if (lp_security() >= SEC_USER) secword |= 1;
204   if (doencrypt) secword |= 2;
205
206   /* decide where (if) to put the encryption challenge, and
207      follow it with the OEM'd domain name
208    */
209   data_len = crypt_len + strlen(global_myworkgroup) + 1;
210
211   set_message(outbuf,17,data_len,True);
212   pstrcpy(smb_buf(outbuf)+crypt_len, global_myworkgroup);
213
214   CVAL(outbuf,smb_vwv1) = secword;
215   SSVALS(outbuf,smb_vwv16+1,crypt_len);
216   if (doencrypt) 
217           memcpy(smb_buf(outbuf), cryptkey, 8);
218
219   Protocol = PROTOCOL_NT1;
220
221   SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
222   SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
223   SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
224   SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
225   SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
226   SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
227   put_long_date(outbuf+smb_vwv11+1,t);
228   SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
229   SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */
230
231   return (smb_len(outbuf)+4);
232 }
233
234 /* these are the protocol lists used for auto architecture detection:
235
236 WinNT 3.51:
237 protocol [PC NETWORK PROGRAM 1.0]
238 protocol [XENIX CORE]
239 protocol [MICROSOFT NETWORKS 1.03]
240 protocol [LANMAN1.0]
241 protocol [Windows for Workgroups 3.1a]
242 protocol [LM1.2X002]
243 protocol [LANMAN2.1]
244 protocol [NT LM 0.12]
245
246 Win95:
247 protocol [PC NETWORK PROGRAM 1.0]
248 protocol [XENIX CORE]
249 protocol [MICROSOFT NETWORKS 1.03]
250 protocol [LANMAN1.0]
251 protocol [Windows for Workgroups 3.1a]
252 protocol [LM1.2X002]
253 protocol [LANMAN2.1]
254 protocol [NT LM 0.12]
255
256 OS/2:
257 protocol [PC NETWORK PROGRAM 1.0]
258 protocol [XENIX CORE]
259 protocol [LANMAN1.0]
260 protocol [LM1.2X002]
261 protocol [LANMAN2.1]
262 */
263
264 /*
265   * Modified to recognize the architecture of the remote machine better.
266   *
267   * This appears to be the matrix of which protocol is used by which
268   * MS product.
269        Protocol                       WfWg    Win95   WinNT  OS/2
270        PC NETWORK PROGRAM 1.0          1       1       1      1
271        XENIX CORE                                      2      2
272        MICROSOFT NETWORKS 3.0          2       2       
273        DOS LM1.2X002                   3       3       
274        MICROSOFT NETWORKS 1.03                         3
275        DOS LANMAN2.1                   4       4       
276        LANMAN1.0                                       4      3
277        Windows for Workgroups 3.1a     5       5       5
278        LM1.2X002                                       6      4
279        LANMAN2.1                                       7      5
280        NT LM 0.12                              6       8
281   *
282   *  tim@fsg.com 09/29/95
283   */
284   
285 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
286 #define ARCH_WIN95    0x2
287 #define ARCH_OS2      0xC      /* Again OS/2 is like NT */
288 #define ARCH_WINNT    0x8
289 #define ARCH_SAMBA    0x10
290  
291 #define ARCH_ALL      0x1F
292  
293 /* List of supported protocols, most desired first */
294 static struct {
295   char *proto_name;
296   char *short_name;
297   int (*proto_reply_fn)(char *);
298   int protocol_level;
299 } supported_protocols[] = {
300   {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
301   {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
302   {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
303   {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
304   {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
305   {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
306   {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
307   {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
308   {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
309   {NULL,NULL},
310 };
311
312
313 /****************************************************************************
314   reply to a negprot
315 ****************************************************************************/
316 int reply_negprot(connection_struct *conn, 
317                   char *inbuf,char *outbuf, int dum_size, 
318                   int dum_buffsize)
319 {
320   int outsize = set_message(outbuf,1,0,True);
321   int Index=0;
322   int choice= -1;
323   int protocol;
324   char *p;
325   int bcc = SVAL(smb_buf(inbuf),-2);
326   int arch = ARCH_ALL;
327
328   p = smb_buf(inbuf)+1;
329   while (p < (smb_buf(inbuf) + bcc))
330     { 
331       Index++;
332       DEBUG(3,("Requested protocol [%s]\n",p));
333       if (strcsequal(p,"Windows for Workgroups 3.1a"))
334         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT );
335       else if (strcsequal(p,"DOS LM1.2X002"))
336         arch &= ( ARCH_WFWG | ARCH_WIN95 );
337       else if (strcsequal(p,"DOS LANMAN2.1"))
338         arch &= ( ARCH_WFWG | ARCH_WIN95 );
339       else if (strcsequal(p,"NT LM 0.12"))
340         arch &= ( ARCH_WIN95 | ARCH_WINNT );
341       else if (strcsequal(p,"LANMAN2.1"))
342         arch &= ( ARCH_WINNT | ARCH_OS2 );
343       else if (strcsequal(p,"LM1.2X002"))
344         arch &= ( ARCH_WINNT | ARCH_OS2 );
345       else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
346         arch &= ARCH_WINNT;
347       else if (strcsequal(p,"XENIX CORE"))
348         arch &= ( ARCH_WINNT | ARCH_OS2 );
349       else if (strcsequal(p,"Samba")) {
350         arch = ARCH_SAMBA;
351         break;
352       }
353  
354       p += strlen(p) + 2;
355     }
356     
357   switch ( arch ) {
358   case ARCH_SAMBA:
359     set_remote_arch(RA_SAMBA);
360     break;
361   case ARCH_WFWG:
362     set_remote_arch(RA_WFWG);
363     break;
364   case ARCH_WIN95:
365     set_remote_arch(RA_WIN95);
366     break;
367   case ARCH_WINNT:
368     set_remote_arch(RA_WINNT);
369     break;
370   case ARCH_OS2:
371     set_remote_arch(RA_OS2);
372     break;
373   default:
374     set_remote_arch(RA_UNKNOWN);
375     break;
376   }
377  
378   /* possibly reload - change of architecture */
379   reload_services(True);      
380     
381   /* a special case to stop password server loops */
382   if (Index == 1 && strequal(remote_machine,myhostname) && 
383       (lp_security()==SEC_SERVER || lp_security()==SEC_DOMAIN))
384     exit_server("Password server loop!");
385   
386   /* Check for protocols, most desirable first */
387   for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
388     {
389       p = smb_buf(inbuf)+1;
390       Index = 0;
391       if (lp_maxprotocol() >= supported_protocols[protocol].protocol_level)
392         while (p < (smb_buf(inbuf) + bcc))
393           { 
394             if (strequal(p,supported_protocols[protocol].proto_name))
395               choice = Index;
396             Index++;
397             p += strlen(p) + 2;
398           }
399       if(choice != -1)
400         break;
401     }
402   
403   SSVAL(outbuf,smb_vwv0,choice);
404   if(choice != -1) {
405     extern fstring remote_proto;
406     fstrcpy(remote_proto,supported_protocols[protocol].short_name);
407     reload_services(True);          
408     outsize = supported_protocols[protocol].proto_reply_fn(outbuf);
409     DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
410   }
411   else {
412     DEBUG(0,("No protocol supported !\n"));
413   }
414   SSVAL(outbuf,smb_vwv0,choice);
415   
416   DEBUG( 5, ( "negprot index=%d\n", choice ) );
417
418   return(outsize);
419 }