s3: only include smb profiling where needed.
[nivanova/samba-autobuild/.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, global_myname());
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         blob_out = data_blob_talloc(ctx, NULL, 16 + blob.length);
238         if (blob_out.data == NULL) {
239                 data_blob_free(&blob);
240                 return data_blob_null;
241         }
242
243         memset(blob_out.data, '\0', 16);
244
245         checked_strlcpy(unix_name, global_myname(), sizeof(unix_name));
246         strlower_m(unix_name);
247         push_ascii_nstring(dos_name, unix_name);
248         safe_strcpy((char *)blob_out.data, dos_name, 16);
249
250 #ifdef DEVELOPER
251         /* Fix valgrind 'uninitialized bytes' issue. */
252         slen = strlen(dos_name);
253         if (slen < 16) {
254                 memset(blob_out.data+slen, '\0', 16 - slen);
255         }
256 #endif
257
258         memcpy(&blob_out.data[16], blob.data, blob.length);
259
260         data_blob_free(&blob);
261
262         return blob_out;
263 }
264
265 /****************************************************************************
266  Reply for the nt protocol.
267 ****************************************************************************/
268
269 static void reply_nt1(struct smb_request *req, uint16 choice)
270 {
271         /* dual names + lock_and_read + nt SMBs + remote API calls */
272         int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
273                 CAP_LEVEL_II_OPLOCKS;
274
275         int secword=0;
276         bool negotiate_spnego = False;
277         struct timespec ts;
278         ssize_t ret;
279         struct smbd_server_connection *sconn = req->sconn;
280
281         sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
282
283         /* Check the flags field to see if this is Vista.
284            WinXP sets it and Vista does not. But we have to 
285            distinguish from NT which doesn't set it either. */
286
287         if ( (req->flags2 & FLAGS2_EXTENDED_SECURITY) &&
288                 ((req->flags2 & FLAGS2_UNKNOWN_BIT4) == 0) )
289         {
290                 if (get_remote_arch() != RA_SAMBA) {
291                         set_remote_arch( RA_VISTA );
292                 }
293         }
294
295         reply_outbuf(req,17,0);
296
297         /* do spnego in user level security if the client
298            supports it and we can do encrypted passwords */
299
300         if (sconn->smb1.negprot.encrypted_passwords &&
301             (lp_security() != SEC_SHARE) &&
302             lp_use_spnego() &&
303             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
304                 negotiate_spnego = True;
305                 capabilities |= CAP_EXTENDED_SECURITY;
306                 add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
307                 /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply
308                    (already partially constructed. */
309                 SSVAL(req->outbuf, smb_flg2,
310                       req->flags2 | FLAGS2_EXTENDED_SECURITY);
311         }
312
313         capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
314
315         if (lp_unix_extensions()) {
316                 capabilities |= CAP_UNIX;
317         }
318
319         if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
320                 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
321
322         if (SMB_OFF_T_BITS == 64)
323                 capabilities |= CAP_LARGE_FILES;
324
325         if (lp_readraw() && lp_writeraw())
326                 capabilities |= CAP_RAW_MODE;
327
328         if (lp_nt_status_support())
329                 capabilities |= CAP_STATUS32;
330
331         if (lp_host_msdfs())
332                 capabilities |= CAP_DFS;
333
334         if (lp_security() >= SEC_USER) {
335                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
336         }
337         if (sconn->smb1.negprot.encrypted_passwords) {
338                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
339         }
340
341         if (lp_server_signing()) {
342                 if (lp_security() >= SEC_USER) {
343                         secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
344                         /* No raw mode with smb signing. */
345                         capabilities &= ~CAP_RAW_MODE;
346                         if (lp_server_signing() == Required)
347                                 secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
348                         srv_set_signing_negotiated(sconn);
349                 } else {
350                         DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
351                         if (lp_server_signing() == Required) {
352                                 exit_server_cleanly("reply_nt1: smb signing required and share level security selected.");
353                         }
354                 }
355         }
356
357         SSVAL(req->outbuf,smb_vwv0,choice);
358         SCVAL(req->outbuf,smb_vwv1,secword);
359
360         set_Protocol(PROTOCOL_NT1);
361
362         SSVAL(req->outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
363         SSVAL(req->outbuf,smb_vwv2+1,1); /* num vcs */
364         SIVAL(req->outbuf,smb_vwv3+1,
365               sconn->smb1.negprot.max_recv); /* max buffer. LOTS! */
366         SIVAL(req->outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
367         SIVAL(req->outbuf,smb_vwv7+1,sys_getpid()); /* session key */
368         SIVAL(req->outbuf,smb_vwv9+1,capabilities); /* capabilities */
369         clock_gettime(CLOCK_REALTIME,&ts);
370         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,(char *)req->outbuf+smb_vwv11+1,ts);
371         SSVALS(req->outbuf,smb_vwv15+1,set_server_zone_offset(ts.tv_sec)/60);
372
373         if (!negotiate_spnego) {
374                 /* Create a token value and add it to the outgoing packet. */
375                 if (sconn->smb1.negprot.encrypted_passwords) {
376                         uint8 chal[8];
377                         /* note that we do not send a challenge at all if
378                            we are using plaintext */
379                         get_challenge(sconn, chal);
380                         ret = message_push_blob(
381                                 &req->outbuf, data_blob_const(chal, sizeof(chal)));
382                         if (ret == -1) {
383                                 DEBUG(0, ("Could not push challenge\n"));
384                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
385                                 return;
386                         }
387                         SCVAL(req->outbuf, smb_vwv16+1, ret);
388                 }
389                 ret = message_push_string(&req->outbuf, lp_workgroup(),
390                                           STR_UNICODE|STR_TERMINATE
391                                           |STR_NOALIGN);
392                 if (ret == -1) {
393                         DEBUG(0, ("Could not push workgroup string\n"));
394                         reply_nterror(req, NT_STATUS_NO_MEMORY);
395                         return;
396                 }
397                 DEBUG(3,("not using SPNEGO\n"));
398         } else {
399                 DATA_BLOB spnego_blob = negprot_spnego(req, req->sconn);
400
401                 if (spnego_blob.data == NULL) {
402                         reply_nterror(req, NT_STATUS_NO_MEMORY);
403                         return;
404                 }
405
406                 ret = message_push_blob(&req->outbuf, spnego_blob);
407                 if (ret == -1) {
408                         DEBUG(0, ("Could not push spnego blob\n"));
409                         reply_nterror(req, NT_STATUS_NO_MEMORY);
410                         return;
411                 }
412                 data_blob_free(&spnego_blob);
413
414                 SCVAL(req->outbuf,smb_vwv16+1, 0);
415                 DEBUG(3,("using SPNEGO\n"));
416         }
417
418         return;
419 }
420
421 /* these are the protocol lists used for auto architecture detection:
422
423 WinNT 3.51:
424 protocol [PC NETWORK PROGRAM 1.0]
425 protocol [XENIX CORE]
426 protocol [MICROSOFT NETWORKS 1.03]
427 protocol [LANMAN1.0]
428 protocol [Windows for Workgroups 3.1a]
429 protocol [LM1.2X002]
430 protocol [LANMAN2.1]
431 protocol [NT LM 0.12]
432
433 Win95:
434 protocol [PC NETWORK PROGRAM 1.0]
435 protocol [XENIX CORE]
436 protocol [MICROSOFT NETWORKS 1.03]
437 protocol [LANMAN1.0]
438 protocol [Windows for Workgroups 3.1a]
439 protocol [LM1.2X002]
440 protocol [LANMAN2.1]
441 protocol [NT LM 0.12]
442
443 Win2K:
444 protocol [PC NETWORK PROGRAM 1.0]
445 protocol [LANMAN1.0]
446 protocol [Windows for Workgroups 3.1a]
447 protocol [LM1.2X002]
448 protocol [LANMAN2.1]
449 protocol [NT LM 0.12]
450
451 Vista:
452 protocol [PC NETWORK PROGRAM 1.0]
453 protocol [LANMAN1.0]
454 protocol [Windows for Workgroups 3.1a]
455 protocol [LM1.2X002]
456 protocol [LANMAN2.1]
457 protocol [NT LM 0.12]
458 protocol [SMB 2.001]
459
460 OS/2:
461 protocol [PC NETWORK PROGRAM 1.0]
462 protocol [XENIX CORE]
463 protocol [LANMAN1.0]
464 protocol [LM1.2X002]
465 protocol [LANMAN2.1]
466 */
467
468 /*
469   * Modified to recognize the architecture of the remote machine better.
470   *
471   * This appears to be the matrix of which protocol is used by which
472   * MS product.
473        Protocol                       WfWg    Win95   WinNT  Win2K  OS/2 Vista
474        PC NETWORK PROGRAM 1.0          1       1       1      1      1     1
475        XENIX CORE                                      2             2
476        MICROSOFT NETWORKS 3.0          2       2       
477        DOS LM1.2X002                   3       3       
478        MICROSOFT NETWORKS 1.03                         3
479        DOS LANMAN2.1                   4       4       
480        LANMAN1.0                                       4      2      3     2
481        Windows for Workgroups 3.1a     5       5       5      3            3
482        LM1.2X002                                       6      4      4     4
483        LANMAN2.1                                       7      5      5     5
484        NT LM 0.12                              6       8      6            6
485        SMB 2.001                                                           7
486   *
487   *  tim@fsg.com 09/29/95
488   *  Win2K added by matty 17/7/99
489   */
490
491 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
492 #define ARCH_WIN95    0x2
493 #define ARCH_WINNT    0x4
494 #define ARCH_WIN2K    0xC      /* Win2K is like NT */
495 #define ARCH_OS2      0x14     /* Again OS/2 is like NT */
496 #define ARCH_SAMBA    0x20
497 #define ARCH_CIFSFS   0x40
498 #define ARCH_VISTA    0x8C     /* Vista is like XP/2K */
499
500 #define ARCH_ALL      0x7F
501
502 /* List of supported protocols, most desired first */
503 static const struct {
504         const char *proto_name;
505         const char *short_name;
506         void (*proto_reply_fn)(struct smb_request *req, uint16 choice);
507         int protocol_level;
508 } supported_protocols[] = {
509         {"SMB 2.002",               "SMB2",     reply_smb2002,  PROTOCOL_SMB2},
510         {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
511         {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
512         {"POSIX 2",                 "NT1",      reply_nt1,      PROTOCOL_NT1},
513         {"LANMAN2.1",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
514         {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
515         {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
516         {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
517         {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
518         {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
519         {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
520         {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
521         {NULL,NULL,NULL,0},
522 };
523
524 /****************************************************************************
525  Reply to a negprot.
526  conn POINTER CAN BE NULL HERE !
527 ****************************************************************************/
528
529 void reply_negprot(struct smb_request *req)
530 {
531         int choice= -1;
532         int protocol;
533         const char *p;
534         int arch = ARCH_ALL;
535         int num_cliprotos;
536         char **cliprotos;
537         int i;
538         size_t converted_size;
539         struct smbd_server_connection *sconn = req->sconn;
540
541         START_PROFILE(SMBnegprot);
542
543         if (sconn->smb1.negprot.done) {
544                 END_PROFILE(SMBnegprot);
545                 exit_server_cleanly("multiple negprot's are not permitted");
546         }
547         sconn->smb1.negprot.done = true;
548
549         if (req->buflen == 0) {
550                 DEBUG(0, ("negprot got no protocols\n"));
551                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
552                 END_PROFILE(SMBnegprot);
553                 return;
554         }
555
556         if (req->buf[req->buflen-1] != '\0') {
557                 DEBUG(0, ("negprot protocols not 0-terminated\n"));
558                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
559                 END_PROFILE(SMBnegprot);
560                 return;
561         }
562
563         p = (const char *)req->buf + 1;
564
565         num_cliprotos = 0;
566         cliprotos = NULL;
567
568         while (smbreq_bufrem(req, p) > 0) {
569
570                 char **tmp;
571
572                 tmp = TALLOC_REALLOC_ARRAY(talloc_tos(), cliprotos, char *,
573                                            num_cliprotos+1);
574                 if (tmp == NULL) {
575                         DEBUG(0, ("talloc failed\n"));
576                         TALLOC_FREE(cliprotos);
577                         reply_nterror(req, NT_STATUS_NO_MEMORY);
578                         END_PROFILE(SMBnegprot);
579                         return;
580                 }
581
582                 cliprotos = tmp;
583
584                 if (!pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p,
585                                        &converted_size)) {
586                         DEBUG(0, ("pull_ascii_talloc failed\n"));
587                         TALLOC_FREE(cliprotos);
588                         reply_nterror(req, NT_STATUS_NO_MEMORY);
589                         END_PROFILE(SMBnegprot);
590                         return;
591                 }
592
593                 DEBUG(3, ("Requested protocol [%s]\n",
594                           cliprotos[num_cliprotos]));
595
596                 num_cliprotos += 1;
597                 p += strlen(p) + 2;
598         }
599
600         for (i=0; i<num_cliprotos; i++) {
601                 if (strcsequal(cliprotos[i], "Windows for Workgroups 3.1a"))
602                         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT
603                                   | ARCH_WIN2K );
604                 else if (strcsequal(cliprotos[i], "DOS LM1.2X002"))
605                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
606                 else if (strcsequal(cliprotos[i], "DOS LANMAN2.1"))
607                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
608                 else if (strcsequal(cliprotos[i], "NT LM 0.12"))
609                         arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K
610                                   | ARCH_CIFSFS);
611                 else if (strcsequal(cliprotos[i], "SMB 2.001"))
612                         arch = ARCH_VISTA;              
613                 else if (strcsequal(cliprotos[i], "LANMAN2.1"))
614                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
615                 else if (strcsequal(cliprotos[i], "LM1.2X002"))
616                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
617                 else if (strcsequal(cliprotos[i], "MICROSOFT NETWORKS 1.03"))
618                         arch &= ARCH_WINNT;
619                 else if (strcsequal(cliprotos[i], "XENIX CORE"))
620                         arch &= ( ARCH_WINNT | ARCH_OS2 );
621                 else if (strcsequal(cliprotos[i], "Samba")) {
622                         arch = ARCH_SAMBA;
623                         break;
624                 } else if (strcsequal(cliprotos[i], "POSIX 2")) {
625                         arch = ARCH_CIFSFS;
626                         break;
627                 }
628         }
629
630         /* CIFSFS can send one arch only, NT LM 0.12. */
631         if (i == 1 && (arch & ARCH_CIFSFS)) {
632                 arch = ARCH_CIFSFS;
633         }
634
635         switch ( arch ) {
636                 case ARCH_CIFSFS:
637                         set_remote_arch(RA_CIFSFS);
638                         break;
639                 case ARCH_SAMBA:
640                         set_remote_arch(RA_SAMBA);
641                         break;
642                 case ARCH_WFWG:
643                         set_remote_arch(RA_WFWG);
644                         break;
645                 case ARCH_WIN95:
646                         set_remote_arch(RA_WIN95);
647                         break;
648                 case ARCH_WINNT:
649                         if(req->flags2 == FLAGS2_WIN2K_SIGNATURE)
650                                 set_remote_arch(RA_WIN2K);
651                         else
652                                 set_remote_arch(RA_WINNT);
653                         break;
654                 case ARCH_WIN2K:
655                         /* Vista may have been set in the negprot so don't 
656                            override it here */
657                         if ( get_remote_arch() != RA_VISTA )
658                                 set_remote_arch(RA_WIN2K);
659                         break;
660                 case ARCH_VISTA:
661                         set_remote_arch(RA_VISTA);
662                         break;
663                 case ARCH_OS2:
664                         set_remote_arch(RA_OS2);
665                         break;
666                 default:
667                         set_remote_arch(RA_UNKNOWN);
668                 break;
669         }
670
671         /* possibly reload - change of architecture */
672         reload_services(sconn->msg_ctx, sconn->sock, True);
673
674         /* moved from the netbios session setup code since we don't have that 
675            when the client connects to port 445.  Of course there is a small
676            window where we are listening to messages   -- jerry */
677
678         serverid_register(sconn_server_id(sconn),
679                           FLAG_MSG_GENERAL|FLAG_MSG_SMBD
680                           |FLAG_MSG_PRINT_GENERAL);
681
682         /* Check for protocols, most desirable first */
683         for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
684                 i = 0;
685                 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
686                                 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
687                         while (i < num_cliprotos) {
688                                 if (strequal(cliprotos[i],supported_protocols[protocol].proto_name))
689                                         choice = i;
690                                 i++;
691                         }
692                 if(choice != -1)
693                         break;
694         }
695
696         if(choice != -1) {
697                 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
698                 reload_services(sconn->msg_ctx, sconn->sock, True);
699                 supported_protocols[protocol].proto_reply_fn(req, choice);
700                 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
701         } else {
702                 DEBUG(0,("No protocol supported !\n"));
703                 reply_outbuf(req, 1, 0);
704                 SSVAL(req->outbuf, smb_vwv0, choice);
705         }
706
707         DEBUG( 5, ( "negprot index=%d\n", choice ) );
708
709         if ((lp_server_signing() == Required) && (get_Protocol() < PROTOCOL_NT1)) {
710                 exit_server_cleanly("SMB signing is required and "
711                         "client negotiated a downlevel protocol");
712         }
713
714         TALLOC_FREE(cliprotos);
715         END_PROFILE(SMBnegprot);
716         return;
717 }