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