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