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