Merge 2610c05b5b95cc7036b3d6dfb894c6cfbdb68483 as Samba-4.0alpha16
[amitay/samba.git] / source3 / smbd / negprot.c
1 /* 
2    Unix SMB/CIFS implementation.
3    negprot reply code
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Volker Lendecke 2007
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 3 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, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "smbd/smbd.h"
23 #include "smbd/globals.h"
24 #include "../libcli/auth/spnego.h"
25 #include "serverid.h"
26 #include "auth.h"
27 #include "messages.h"
28 #include "smbprofile.h"
29
30 extern fstring remote_proto;
31
32 static void get_challenge(struct smbd_server_connection *sconn, uint8 buff[8])
33 {
34         NTSTATUS nt_status;
35
36         /* We might be called more than once, multiple negprots are
37          * permitted */
38         if (sconn->smb1.negprot.auth_context) {
39                 DEBUG(3, ("get challenge: is this a secondary negprot? "
40                           "sconn->negprot.auth_context is non-NULL!\n"));
41                         TALLOC_FREE(sconn->smb1.negprot.auth_context);
42         }
43
44         DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
45         nt_status = make_auth_context_subsystem(
46                 sconn, &sconn->smb1.negprot.auth_context);
47         if (!NT_STATUS_IS_OK(nt_status)) {
48                 DEBUG(0, ("make_auth_context_subsystem returned %s",
49                           nt_errstr(nt_status)));
50                 smb_panic("cannot make_negprot_global_auth_context!");
51         }
52         DEBUG(10, ("get challenge: getting challenge\n"));
53         sconn->smb1.negprot.auth_context->get_ntlm_challenge(
54                 sconn->smb1.negprot.auth_context, buff);
55 }
56
57 /****************************************************************************
58  Reply for the core protocol.
59 ****************************************************************************/
60
61 static void reply_corep(struct smb_request *req, uint16 choice)
62 {
63         reply_outbuf(req, 1, 0);
64         SSVAL(req->outbuf, smb_vwv0, choice);
65
66         set_Protocol(PROTOCOL_CORE);
67 }
68
69 /****************************************************************************
70  Reply for the coreplus protocol.
71 ****************************************************************************/
72
73 static void reply_coreplus(struct smb_request *req, uint16 choice)
74 {
75         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
76
77         reply_outbuf(req, 13, 0);
78
79         SSVAL(req->outbuf,smb_vwv0,choice);
80         SSVAL(req->outbuf,smb_vwv5,raw); /* tell redirector we support
81                         readbraw and writebraw (possibly) */
82         /* Reply, SMBlockread, SMBwritelock supported. */
83         SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
84         SSVAL(req->outbuf,smb_vwv1,0x1); /* user level security, don't
85                                           * encrypt */
86         set_Protocol(PROTOCOL_COREPLUS);
87 }
88
89 /****************************************************************************
90  Reply for the lanman 1.0 protocol.
91 ****************************************************************************/
92
93 static void reply_lanman1(struct smb_request *req, uint16 choice)
94 {
95         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
96         int secword=0;
97         time_t t = time(NULL);
98         struct smbd_server_connection *sconn = req->sconn;
99
100         sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
101
102         if (lp_security()>=SEC_USER) {
103                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
104         }
105         if (sconn->smb1.negprot.encrypted_passwords) {
106                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
107         }
108
109         reply_outbuf(req, 13, sconn->smb1.negprot.encrypted_passwords?8:0);
110
111         SSVAL(req->outbuf,smb_vwv0,choice);
112         SSVAL(req->outbuf,smb_vwv1,secword);
113         /* Create a token value and add it to the outgoing packet. */
114         if (sconn->smb1.negprot.encrypted_passwords) {
115                 get_challenge(sconn, (uint8 *)smb_buf(req->outbuf));
116                 SSVAL(req->outbuf,smb_vwv11, 8);
117         }
118
119         set_Protocol(PROTOCOL_LANMAN1);
120
121         /* Reply, SMBlockread, SMBwritelock supported. */
122         SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
123         SSVAL(req->outbuf,smb_vwv2,sconn->smb1.negprot.max_recv);
124         SSVAL(req->outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
125         SSVAL(req->outbuf,smb_vwv4,1);
126         SSVAL(req->outbuf,smb_vwv5,raw); /* tell redirector we support
127                 readbraw writebraw (possibly) */
128         SIVAL(req->outbuf,smb_vwv6,sys_getpid());
129         SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60);
130
131         srv_put_dos_date((char *)req->outbuf,smb_vwv8,t);
132
133         return;
134 }
135
136 /****************************************************************************
137  Reply for the lanman 2.0 protocol.
138 ****************************************************************************/
139
140 static void reply_lanman2(struct smb_request *req, uint16 choice)
141 {
142         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
143         int secword=0;
144         time_t t = time(NULL);
145         struct smbd_server_connection *sconn = req->sconn;
146
147         sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
148
149         if (lp_security()>=SEC_USER) {
150                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
151         }
152         if (sconn->smb1.negprot.encrypted_passwords) {
153                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
154         }
155
156         reply_outbuf(req, 13, sconn->smb1.negprot.encrypted_passwords?8:0);
157
158         SSVAL(req->outbuf,smb_vwv0,choice);
159         SSVAL(req->outbuf,smb_vwv1,secword);
160         SIVAL(req->outbuf,smb_vwv6,sys_getpid());
161
162         /* Create a token value and add it to the outgoing packet. */
163         if (sconn->smb1.negprot.encrypted_passwords) {
164                 get_challenge(sconn, (uint8 *)smb_buf(req->outbuf));
165                 SSVAL(req->outbuf,smb_vwv11, 8);
166         }
167
168         set_Protocol(PROTOCOL_LANMAN2);
169
170         /* Reply, SMBlockread, SMBwritelock supported. */
171         SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
172         SSVAL(req->outbuf,smb_vwv2,sconn->smb1.negprot.max_recv);
173         SSVAL(req->outbuf,smb_vwv3,lp_maxmux());
174         SSVAL(req->outbuf,smb_vwv4,1);
175         SSVAL(req->outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
176         SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60);
177         srv_put_dos_date((char *)req->outbuf,smb_vwv8,t);
178 }
179
180 /****************************************************************************
181  Generate the spnego negprot reply blob. Return the number of bytes used.
182 ****************************************************************************/
183
184 DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn)
185 {
186         DATA_BLOB blob = data_blob_null;
187         DATA_BLOB blob_out = data_blob_null;
188         nstring dos_name;
189         fstring unix_name;
190 #ifdef DEVELOPER
191         size_t slen;
192 #endif
193         const char *OIDs_krb5[] = {OID_KERBEROS5,
194                                    OID_KERBEROS5_OLD,
195                                    OID_NTLMSSP,
196                                    NULL};
197         const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
198
199         sconn->smb1.negprot.spnego = true;
200         /* strangely enough, NT does not sent the single OID NTLMSSP when
201            not a ADS member, it sends no OIDs at all
202
203            OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know
204                    about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"
205
206            Our sessionsetup code now handles raw NTLMSSP connects, so we can go
207            back to doing what W2K3 does here. This is needed to make PocketPC 2003
208            CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
209            for details. JRA.
210
211         */
212
213         if (lp_security() != SEC_ADS && !USE_KERBEROS_KEYTAB) {
214 #if 0
215                 /* Code for PocketPC client */
216                 blob = data_blob(guid, 16);
217 #else
218                 /* Code for standalone WXP client */
219                 blob = spnego_gen_negTokenInit(ctx, OIDs_ntlm, NULL, "NONE");
220 #endif
221         } else if (!lp_send_spnego_principal()) {
222                 /* By default, Windows 2008 and later sends not_defined_in_RFC4178@please_ignore */
223                 blob = spnego_gen_negTokenInit(ctx, OIDs_krb5, NULL, ADS_IGNORE_PRINCIPAL);
224         } else {
225                 fstring myname;
226                 char *host_princ_s = NULL;
227                 name_to_fqdn(myname, lp_netbios_name());
228                 strlower_m(myname);
229                 if (asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm())
230                     == -1) {
231                         return data_blob_null;
232                 }
233                 blob = spnego_gen_negTokenInit(ctx, OIDs_krb5, NULL, host_princ_s);
234                 SAFE_FREE(host_princ_s);
235         }
236
237         if (blob.length == 0 || blob.data == NULL) {
238                 return data_blob_null;
239         }
240
241         blob_out = data_blob_talloc(ctx, NULL, 16 + blob.length);
242         if (blob_out.data == NULL) {
243                 data_blob_free(&blob);
244                 return data_blob_null;
245         }
246
247         memset(blob_out.data, '\0', 16);
248
249         checked_strlcpy(unix_name, lp_netbios_name(), sizeof(unix_name));
250         strlower_m(unix_name);
251         push_ascii_nstring(dos_name, unix_name);
252         strlcpy((char *)blob_out.data, dos_name, 17);
253
254 #ifdef DEVELOPER
255         /* Fix valgrind 'uninitialized bytes' issue. */
256         slen = strlen(dos_name);
257         if (slen < 16) {
258                 memset(blob_out.data+slen, '\0', 16 - slen);
259         }
260 #endif
261
262         memcpy(&blob_out.data[16], blob.data, blob.length);
263
264         data_blob_free(&blob);
265
266         return blob_out;
267 }
268
269 /****************************************************************************
270  Reply for the nt protocol.
271 ****************************************************************************/
272
273 static void reply_nt1(struct smb_request *req, uint16 choice)
274 {
275         /* dual names + lock_and_read + nt SMBs + remote API calls */
276         int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
277                 CAP_LEVEL_II_OPLOCKS;
278
279         int secword=0;
280         bool negotiate_spnego = False;
281         struct timespec ts;
282         ssize_t ret;
283         struct smbd_server_connection *sconn = req->sconn;
284
285         sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
286
287         /* Check the flags field to see if this is Vista.
288            WinXP sets it and Vista does not. But we have to 
289            distinguish from NT which doesn't set it either. */
290
291         if ( (req->flags2 & FLAGS2_EXTENDED_SECURITY) &&
292                 ((req->flags2 & FLAGS2_UNKNOWN_BIT4) == 0) )
293         {
294                 if (get_remote_arch() != RA_SAMBA) {
295                         set_remote_arch( RA_VISTA );
296                 }
297         }
298
299         reply_outbuf(req,17,0);
300
301         /* do spnego in user level security if the client
302            supports it and we can do encrypted passwords */
303
304         if (sconn->smb1.negprot.encrypted_passwords &&
305             (lp_security() != SEC_SHARE) &&
306             lp_use_spnego() &&
307             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
308                 negotiate_spnego = True;
309                 capabilities |= CAP_EXTENDED_SECURITY;
310                 add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
311                 /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply
312                    (already partially constructed. */
313                 SSVAL(req->outbuf, smb_flg2,
314                       req->flags2 | FLAGS2_EXTENDED_SECURITY);
315         }
316
317         capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
318
319         if (lp_unix_extensions()) {
320                 capabilities |= CAP_UNIX;
321         }
322
323         if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
324                 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
325
326         if (SMB_OFF_T_BITS == 64)
327                 capabilities |= CAP_LARGE_FILES;
328
329         if (lp_readraw() && lp_writeraw())
330                 capabilities |= CAP_RAW_MODE;
331
332         if (lp_nt_status_support())
333                 capabilities |= CAP_STATUS32;
334
335         if (lp_host_msdfs())
336                 capabilities |= CAP_DFS;
337
338         if (lp_security() >= SEC_USER) {
339                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
340         }
341         if (sconn->smb1.negprot.encrypted_passwords) {
342                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
343         }
344
345         if (lp_server_signing()) {
346                 if (lp_security() >= SEC_USER) {
347                         secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
348                         /* No raw mode with smb signing. */
349                         capabilities &= ~CAP_RAW_MODE;
350                         if (lp_server_signing() == Required)
351                                 secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
352                         srv_set_signing_negotiated(sconn);
353                 } else {
354                         DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
355                         if (lp_server_signing() == Required) {
356                                 exit_server_cleanly("reply_nt1: smb signing required and share level security selected.");
357                         }
358                 }
359         }
360
361         SSVAL(req->outbuf,smb_vwv0,choice);
362         SCVAL(req->outbuf,smb_vwv1,secword);
363
364         set_Protocol(PROTOCOL_NT1);
365
366         SSVAL(req->outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
367         SSVAL(req->outbuf,smb_vwv2+1,1); /* num vcs */
368         SIVAL(req->outbuf,smb_vwv3+1,
369               sconn->smb1.negprot.max_recv); /* max buffer. LOTS! */
370         SIVAL(req->outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
371         SIVAL(req->outbuf,smb_vwv7+1,sys_getpid()); /* session key */
372         SIVAL(req->outbuf,smb_vwv9+1,capabilities); /* capabilities */
373         clock_gettime(CLOCK_REALTIME,&ts);
374         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,(char *)req->outbuf+smb_vwv11+1,ts);
375         SSVALS(req->outbuf,smb_vwv15+1,set_server_zone_offset(ts.tv_sec)/60);
376
377         if (!negotiate_spnego) {
378                 /* Create a token value and add it to the outgoing packet. */
379                 if (sconn->smb1.negprot.encrypted_passwords) {
380                         uint8 chal[8];
381                         /* note that we do not send a challenge at all if
382                            we are using plaintext */
383                         get_challenge(sconn, chal);
384                         ret = message_push_blob(
385                                 &req->outbuf, data_blob_const(chal, sizeof(chal)));
386                         if (ret == -1) {
387                                 DEBUG(0, ("Could not push challenge\n"));
388                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
389                                 return;
390                         }
391                         SCVAL(req->outbuf, smb_vwv16+1, ret);
392                 }
393                 ret = message_push_string(&req->outbuf, lp_workgroup(),
394                                           STR_UNICODE|STR_TERMINATE
395                                           |STR_NOALIGN);
396                 if (ret == -1) {
397                         DEBUG(0, ("Could not push workgroup string\n"));
398                         reply_nterror(req, NT_STATUS_NO_MEMORY);
399                         return;
400                 }
401                 DEBUG(3,("not using SPNEGO\n"));
402         } else {
403                 DATA_BLOB spnego_blob = negprot_spnego(req, req->sconn);
404
405                 if (spnego_blob.data == NULL) {
406                         reply_nterror(req, NT_STATUS_NO_MEMORY);
407                         return;
408                 }
409
410                 ret = message_push_blob(&req->outbuf, spnego_blob);
411                 if (ret == -1) {
412                         DEBUG(0, ("Could not push spnego blob\n"));
413                         reply_nterror(req, NT_STATUS_NO_MEMORY);
414                         return;
415                 }
416                 data_blob_free(&spnego_blob);
417
418                 SCVAL(req->outbuf,smb_vwv16+1, 0);
419                 DEBUG(3,("using SPNEGO\n"));
420         }
421
422         return;
423 }
424
425 /* these are the protocol lists used for auto architecture detection:
426
427 WinNT 3.51:
428 protocol [PC NETWORK PROGRAM 1.0]
429 protocol [XENIX CORE]
430 protocol [MICROSOFT NETWORKS 1.03]
431 protocol [LANMAN1.0]
432 protocol [Windows for Workgroups 3.1a]
433 protocol [LM1.2X002]
434 protocol [LANMAN2.1]
435 protocol [NT LM 0.12]
436
437 Win95:
438 protocol [PC NETWORK PROGRAM 1.0]
439 protocol [XENIX CORE]
440 protocol [MICROSOFT NETWORKS 1.03]
441 protocol [LANMAN1.0]
442 protocol [Windows for Workgroups 3.1a]
443 protocol [LM1.2X002]
444 protocol [LANMAN2.1]
445 protocol [NT LM 0.12]
446
447 Win2K:
448 protocol [PC NETWORK PROGRAM 1.0]
449 protocol [LANMAN1.0]
450 protocol [Windows for Workgroups 3.1a]
451 protocol [LM1.2X002]
452 protocol [LANMAN2.1]
453 protocol [NT LM 0.12]
454
455 Vista:
456 protocol [PC NETWORK PROGRAM 1.0]
457 protocol [LANMAN1.0]
458 protocol [Windows for Workgroups 3.1a]
459 protocol [LM1.2X002]
460 protocol [LANMAN2.1]
461 protocol [NT LM 0.12]
462 protocol [SMB 2.001]
463
464 OS/2:
465 protocol [PC NETWORK PROGRAM 1.0]
466 protocol [XENIX CORE]
467 protocol [LANMAN1.0]
468 protocol [LM1.2X002]
469 protocol [LANMAN2.1]
470 */
471
472 /*
473   * Modified to recognize the architecture of the remote machine better.
474   *
475   * This appears to be the matrix of which protocol is used by which
476   * MS product.
477        Protocol                       WfWg    Win95   WinNT  Win2K  OS/2 Vista
478        PC NETWORK PROGRAM 1.0          1       1       1      1      1     1
479        XENIX CORE                                      2             2
480        MICROSOFT NETWORKS 3.0          2       2       
481        DOS LM1.2X002                   3       3       
482        MICROSOFT NETWORKS 1.03                         3
483        DOS LANMAN2.1                   4       4       
484        LANMAN1.0                                       4      2      3     2
485        Windows for Workgroups 3.1a     5       5       5      3            3
486        LM1.2X002                                       6      4      4     4
487        LANMAN2.1                                       7      5      5     5
488        NT LM 0.12                              6       8      6            6
489        SMB 2.001                                                           7
490   *
491   *  tim@fsg.com 09/29/95
492   *  Win2K added by matty 17/7/99
493   */
494
495 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
496 #define ARCH_WIN95    0x2
497 #define ARCH_WINNT    0x4
498 #define ARCH_WIN2K    0xC      /* Win2K is like NT */
499 #define ARCH_OS2      0x14     /* Again OS/2 is like NT */
500 #define ARCH_SAMBA    0x20
501 #define ARCH_CIFSFS   0x40
502 #define ARCH_VISTA    0x8C     /* Vista is like XP/2K */
503
504 #define ARCH_ALL      0x7F
505
506 /* List of supported protocols, most desired first */
507 static const struct {
508         const char *proto_name;
509         const char *short_name;
510         void (*proto_reply_fn)(struct smb_request *req, uint16 choice);
511         int protocol_level;
512 } supported_protocols[] = {
513         {"SMB 2.002",               "SMB2",     reply_smb2002,  PROTOCOL_SMB2},
514         {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
515         {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
516         {"POSIX 2",                 "NT1",      reply_nt1,      PROTOCOL_NT1},
517         {"LANMAN2.1",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
518         {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
519         {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
520         {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
521         {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
522         {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
523         {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
524         {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
525         {NULL,NULL,NULL,0},
526 };
527
528 /****************************************************************************
529  Reply to a negprot.
530  conn POINTER CAN BE NULL HERE !
531 ****************************************************************************/
532
533 void reply_negprot(struct smb_request *req)
534 {
535         int choice= -1;
536         int protocol;
537         const char *p;
538         int arch = ARCH_ALL;
539         int num_cliprotos;
540         char **cliprotos;
541         int i;
542         size_t converted_size;
543         struct smbd_server_connection *sconn = req->sconn;
544
545         START_PROFILE(SMBnegprot);
546
547         if (sconn->smb1.negprot.done) {
548                 END_PROFILE(SMBnegprot);
549                 exit_server_cleanly("multiple negprot's are not permitted");
550         }
551         sconn->smb1.negprot.done = true;
552
553         if (req->buflen == 0) {
554                 DEBUG(0, ("negprot got no protocols\n"));
555                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
556                 END_PROFILE(SMBnegprot);
557                 return;
558         }
559
560         if (req->buf[req->buflen-1] != '\0') {
561                 DEBUG(0, ("negprot protocols not 0-terminated\n"));
562                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
563                 END_PROFILE(SMBnegprot);
564                 return;
565         }
566
567         p = (const char *)req->buf + 1;
568
569         num_cliprotos = 0;
570         cliprotos = NULL;
571
572         while (smbreq_bufrem(req, p) > 0) {
573
574                 char **tmp;
575
576                 tmp = talloc_realloc(talloc_tos(), cliprotos, char *,
577                                            num_cliprotos+1);
578                 if (tmp == NULL) {
579                         DEBUG(0, ("talloc failed\n"));
580                         TALLOC_FREE(cliprotos);
581                         reply_nterror(req, NT_STATUS_NO_MEMORY);
582                         END_PROFILE(SMBnegprot);
583                         return;
584                 }
585
586                 cliprotos = tmp;
587
588                 if (!pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p,
589                                        &converted_size)) {
590                         DEBUG(0, ("pull_ascii_talloc failed\n"));
591                         TALLOC_FREE(cliprotos);
592                         reply_nterror(req, NT_STATUS_NO_MEMORY);
593                         END_PROFILE(SMBnegprot);
594                         return;
595                 }
596
597                 DEBUG(3, ("Requested protocol [%s]\n",
598                           cliprotos[num_cliprotos]));
599
600                 num_cliprotos += 1;
601                 p += strlen(p) + 2;
602         }
603
604         for (i=0; i<num_cliprotos; i++) {
605                 if (strcsequal(cliprotos[i], "Windows for Workgroups 3.1a"))
606                         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT
607                                   | ARCH_WIN2K );
608                 else if (strcsequal(cliprotos[i], "DOS LM1.2X002"))
609                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
610                 else if (strcsequal(cliprotos[i], "DOS LANMAN2.1"))
611                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
612                 else if (strcsequal(cliprotos[i], "NT LM 0.12"))
613                         arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K
614                                   | ARCH_CIFSFS);
615                 else if (strcsequal(cliprotos[i], "SMB 2.001"))
616                         arch = ARCH_VISTA;              
617                 else if (strcsequal(cliprotos[i], "LANMAN2.1"))
618                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
619                 else if (strcsequal(cliprotos[i], "LM1.2X002"))
620                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
621                 else if (strcsequal(cliprotos[i], "MICROSOFT NETWORKS 1.03"))
622                         arch &= ARCH_WINNT;
623                 else if (strcsequal(cliprotos[i], "XENIX CORE"))
624                         arch &= ( ARCH_WINNT | ARCH_OS2 );
625                 else if (strcsequal(cliprotos[i], "Samba")) {
626                         arch = ARCH_SAMBA;
627                         break;
628                 } else if (strcsequal(cliprotos[i], "POSIX 2")) {
629                         arch = ARCH_CIFSFS;
630                         break;
631                 }
632         }
633
634         /* CIFSFS can send one arch only, NT LM 0.12. */
635         if (i == 1 && (arch & ARCH_CIFSFS)) {
636                 arch = ARCH_CIFSFS;
637         }
638
639         switch ( arch ) {
640                 case ARCH_CIFSFS:
641                         set_remote_arch(RA_CIFSFS);
642                         break;
643                 case ARCH_SAMBA:
644                         set_remote_arch(RA_SAMBA);
645                         break;
646                 case ARCH_WFWG:
647                         set_remote_arch(RA_WFWG);
648                         break;
649                 case ARCH_WIN95:
650                         set_remote_arch(RA_WIN95);
651                         break;
652                 case ARCH_WINNT:
653                         if(req->flags2 == FLAGS2_WIN2K_SIGNATURE)
654                                 set_remote_arch(RA_WIN2K);
655                         else
656                                 set_remote_arch(RA_WINNT);
657                         break;
658                 case ARCH_WIN2K:
659                         /* Vista may have been set in the negprot so don't 
660                            override it here */
661                         if ( get_remote_arch() != RA_VISTA )
662                                 set_remote_arch(RA_WIN2K);
663                         break;
664                 case ARCH_VISTA:
665                         set_remote_arch(RA_VISTA);
666                         break;
667                 case ARCH_OS2:
668                         set_remote_arch(RA_OS2);
669                         break;
670                 default:
671                         set_remote_arch(RA_UNKNOWN);
672                 break;
673         }
674
675         /* possibly reload - change of architecture */
676         reload_services(sconn->msg_ctx, sconn->sock, True);
677
678         /* moved from the netbios session setup code since we don't have that 
679            when the client connects to port 445.  Of course there is a small
680            window where we are listening to messages   -- jerry */
681
682         serverid_register(sconn_server_id(sconn),
683                           FLAG_MSG_GENERAL|FLAG_MSG_SMBD
684                           |FLAG_MSG_PRINT_GENERAL);
685
686         /* Check for protocols, most desirable first */
687         for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
688                 i = 0;
689                 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
690                                 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
691                         while (i < num_cliprotos) {
692                                 if (strequal(cliprotos[i],supported_protocols[protocol].proto_name))
693                                         choice = i;
694                                 i++;
695                         }
696                 if(choice != -1)
697                         break;
698         }
699
700         if(choice != -1) {
701                 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
702                 reload_services(sconn->msg_ctx, sconn->sock, True);
703                 supported_protocols[protocol].proto_reply_fn(req, choice);
704                 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
705         } else {
706                 DEBUG(0,("No protocol supported !\n"));
707                 reply_outbuf(req, 1, 0);
708                 SSVAL(req->outbuf, smb_vwv0, choice);
709         }
710
711         DEBUG( 5, ( "negprot index=%d\n", choice ) );
712
713         if ((lp_server_signing() == Required) && (get_Protocol() < PROTOCOL_NT1)) {
714                 exit_server_cleanly("SMB signing is required and "
715                         "client negotiated a downlevel protocol");
716         }
717
718         TALLOC_FREE(cliprotos);
719
720         if (lp_async_smb_echo_handler() && !fork_echo_handler(sconn)) {
721                 exit_server("Failed to fork echo handler");
722         }
723
724         END_PROFILE(SMBnegprot);
725         return;
726 }