Initial import
[samba] / source / smbd / negprot.c
1 /* 
2    Unix SMB/CIFS implementation.
3    negprot reply code
4    Copyright (C) Andrew Tridgell 1992-1998
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 extern fstring remote_proto;
24 extern enum protocol_types Protocol;
25 extern int max_recv;
26
27 BOOL global_encrypted_passwords_negotiated = False;
28 BOOL global_spnego_negotiated = False;
29 struct auth_context *negprot_global_auth_context = NULL;
30
31 static void get_challenge(char buff[8]) 
32 {
33         NTSTATUS nt_status;
34         const uint8 *cryptkey;
35
36         /* We might be called more than once, muliple negprots are premitted */
37         if (negprot_global_auth_context) {
38                 DEBUG(3, ("get challenge: is this a secondary negprot?  negprot_global_auth_context is non-NULL!\n"));
39                 (negprot_global_auth_context->free)(&negprot_global_auth_context);
40         }
41
42         DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
43         if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) {
44                 DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status)));
45                 smb_panic("cannot make_negprot_global_auth_context!\n");
46         }
47         DEBUG(10, ("get challenge: getting challenge\n"));
48         cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context);
49         memcpy(buff, cryptkey, 8);
50 }
51
52 /****************************************************************************
53  Reply for the core protocol.
54 ****************************************************************************/
55
56 static int reply_corep(char *inbuf, char *outbuf)
57 {
58         int outsize = set_message(outbuf,1,0,True);
59
60         Protocol = PROTOCOL_CORE;
61         
62         return outsize;
63 }
64
65 /****************************************************************************
66  Reply for the coreplus protocol.
67 ****************************************************************************/
68
69 static int reply_coreplus(char *inbuf, char *outbuf)
70 {
71         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
72         int outsize = set_message(outbuf,13,0,True);
73         SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
74                         readbraw and writebraw (possibly) */
75         /* Reply, SMBlockread, SMBwritelock supported. */
76         SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
77         SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */    
78
79         Protocol = PROTOCOL_COREPLUS;
80
81         return outsize;
82 }
83
84 /****************************************************************************
85  Reply for the lanman 1.0 protocol.
86 ****************************************************************************/
87
88 static int reply_lanman1(char *inbuf, char *outbuf)
89 {
90         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
91         int secword=0;
92         time_t t = time(NULL);
93
94         global_encrypted_passwords_negotiated = lp_encrypted_passwords();
95
96         if (lp_security()>=SEC_USER)
97                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
98         if (global_encrypted_passwords_negotiated)
99                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
100
101         set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
102         SSVAL(outbuf,smb_vwv1,secword); 
103         /* Create a token value and add it to the outgoing packet. */
104         if (global_encrypted_passwords_negotiated) {
105                 get_challenge(smb_buf(outbuf));
106                 SSVAL(outbuf,smb_vwv11, 8);
107         }
108
109         Protocol = PROTOCOL_LANMAN1;
110
111         /* Reply, SMBlockread, SMBwritelock supported. */
112         SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
113         SSVAL(outbuf,smb_vwv2,max_recv);
114         SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
115         SSVAL(outbuf,smb_vwv4,1);
116         SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
117                 readbraw writebraw (possibly) */
118         SIVAL(outbuf,smb_vwv6,sys_getpid());
119         SSVAL(outbuf,smb_vwv10, set_server_zone_offset(t)/60);
120
121         srv_put_dos_date(outbuf,smb_vwv8,t);
122
123         return (smb_len(outbuf)+4);
124 }
125
126 /****************************************************************************
127  Reply for the lanman 2.0 protocol.
128 ****************************************************************************/
129
130 static int reply_lanman2(char *inbuf, char *outbuf)
131 {
132         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
133         int secword=0;
134         time_t t = time(NULL);
135
136         global_encrypted_passwords_negotiated = lp_encrypted_passwords();
137   
138         if (lp_security()>=SEC_USER)
139                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
140         if (global_encrypted_passwords_negotiated)
141                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
142
143         set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
144         SSVAL(outbuf,smb_vwv1,secword); 
145         SIVAL(outbuf,smb_vwv6,sys_getpid());
146
147         /* Create a token value and add it to the outgoing packet. */
148         if (global_encrypted_passwords_negotiated) {
149                 get_challenge(smb_buf(outbuf));
150                 SSVAL(outbuf,smb_vwv11, 8);
151         }
152
153         Protocol = PROTOCOL_LANMAN2;
154
155         /* Reply, SMBlockread, SMBwritelock supported. */
156         SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
157         SSVAL(outbuf,smb_vwv2,max_recv);
158         SSVAL(outbuf,smb_vwv3,lp_maxmux()); 
159         SSVAL(outbuf,smb_vwv4,1);
160         SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
161         SSVAL(outbuf,smb_vwv10, set_server_zone_offset(t)/60);
162         srv_put_dos_date(outbuf,smb_vwv8,t);
163
164         return (smb_len(outbuf)+4);
165 }
166
167 /****************************************************************************
168  Generate the spnego negprot reply blob. Return the number of bytes used.
169 ****************************************************************************/
170
171 static int negprot_spnego(char *p, uint8 *pkeylen)
172 {
173         DATA_BLOB blob;
174         nstring dos_name;
175         fstring unix_name;
176         char guid[17];
177         const char *OIDs_krb5[] = {OID_KERBEROS5,
178                                    OID_KERBEROS5_OLD,
179                                    OID_NTLMSSP,
180                                    NULL};
181         const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
182         int len;
183
184         global_spnego_negotiated = True;
185
186         ZERO_STRUCT(guid);
187
188         safe_strcpy(unix_name, global_myname(), sizeof(unix_name)-1);
189         strlower_m(unix_name);
190         push_ascii_nstring(dos_name, unix_name);
191         safe_strcpy(guid, dos_name, sizeof(guid)-1);
192
193 #ifdef DEVELOPER
194         /* valgrind fixer... */
195         {
196                 size_t sl = strlen(guid);
197                 if (sizeof(guid)-sl)
198                         memset(&guid[sl], '\0', sizeof(guid)-sl);
199         }
200 #endif
201
202         /* strangely enough, NT does not sent the single OID NTLMSSP when
203            not a ADS member, it sends no OIDs at all
204
205            OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know
206                    about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"
207
208            Our sessionsetup code now handles raw NTLMSSP connects, so we can go
209            back to doing what W2K3 does here. This is needed to make PocketPC 2003
210            CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
211            for details. JRA.
212
213         */
214
215         if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) {
216 #if 0
217                 /* Code for PocketPC client */
218                 blob = data_blob(guid, 16);
219 #else
220                 /* Code for standalone WXP client */
221                 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
222 #endif
223         } else {
224                 fstring myname;
225                 char *host_princ_s = NULL;
226                 name_to_fqdn(myname, global_myname());
227                 strlower_m(myname);
228                 asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm());
229                 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s);
230                 SAFE_FREE(host_princ_s);
231         }
232
233         memcpy(p, blob.data, blob.length);
234         len = blob.length;
235         if (len > 256) {
236                 DEBUG(0,("negprot_spnego: blob length too long (%d)\n", len));
237                 len = 255;
238         }
239         data_blob_free(&blob);
240
241         if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) {
242                 *pkeylen = 0;
243         } else {
244                 *pkeylen = len;
245         }
246         return len;
247 }
248
249 /****************************************************************************
250  Reply for the nt protocol.
251 ****************************************************************************/
252
253 static int reply_nt1(char *inbuf, char *outbuf)
254 {
255         /* dual names + lock_and_read + nt SMBs + remote API calls */
256         int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
257                 CAP_LEVEL_II_OPLOCKS;
258
259         int secword=0;
260         char *p, *q;
261         BOOL negotiate_spnego = False;
262         time_t t = time(NULL);
263
264         global_encrypted_passwords_negotiated = lp_encrypted_passwords();
265
266         /* do spnego in user level security if the client
267            supports it and we can do encrypted passwords */
268         
269         if (global_encrypted_passwords_negotiated && 
270             (lp_security() != SEC_SHARE) &&
271             lp_use_spnego() &&
272             (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
273                 negotiate_spnego = True;
274                 capabilities |= CAP_EXTENDED_SECURITY;
275                 add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
276                 /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply (already
277                         partially constructed. */
278                 SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_EXTENDED_SECURITY);
279         }
280         
281         capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
282
283         if (lp_unix_extensions()) {
284                 capabilities |= CAP_UNIX;
285         }
286         
287         if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
288                 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
289         
290         if (SMB_OFF_T_BITS == 64)
291                 capabilities |= CAP_LARGE_FILES;
292
293         if (lp_readraw() && lp_writeraw())
294                 capabilities |= CAP_RAW_MODE;
295         
296         if (lp_nt_status_support())
297                 capabilities |= CAP_STATUS32;
298         
299         if (lp_host_msdfs())
300                 capabilities |= CAP_DFS;
301         
302         if (lp_security() >= SEC_USER)
303                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
304         if (global_encrypted_passwords_negotiated)
305                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
306         
307         if (lp_server_signing()) {
308                 if (lp_security() >= SEC_USER) {
309                         secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
310                         /* No raw mode with smb signing. */
311                         capabilities &= ~CAP_RAW_MODE;
312                         if (lp_server_signing() == Required)
313                                 secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
314                         srv_set_signing_negotiated();
315                 } else {
316                         DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
317                         if (lp_server_signing() == Required) {
318                                 exit_server("reply_nt1: smb signing required and share level security selected.");
319                         }
320                 }
321         }
322
323         set_message(outbuf,17,0,True);
324         
325         SCVAL(outbuf,smb_vwv1,secword);
326         
327         Protocol = PROTOCOL_NT1;
328         
329         SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
330         SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
331         SIVAL(outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */
332         SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
333         SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
334         SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
335         put_long_date(outbuf+smb_vwv11+1,t);
336         SSVALS(outbuf,smb_vwv15+1,set_server_zone_offset(t)/60);
337         
338         p = q = smb_buf(outbuf);
339         if (!negotiate_spnego) {
340                 /* Create a token value and add it to the outgoing packet. */
341                 if (global_encrypted_passwords_negotiated) {
342                         /* note that we do not send a challenge at all if
343                            we are using plaintext */
344                         get_challenge(p);
345                         SCVAL(outbuf,smb_vwv16+1,8);
346                         p += 8;
347                 }
348                 p += srvstr_push(outbuf, p, lp_workgroup(), -1, 
349                                  STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
350                 DEBUG(3,("not using SPNEGO\n"));
351         } else {
352                 uint8 keylen;
353                 int len = negprot_spnego(p, &keylen);
354                 
355                 SCVAL(outbuf,smb_vwv16+1,keylen);
356                 p += len;
357                 DEBUG(3,("using SPNEGO\n"));
358         }
359         
360         SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
361         set_message_end(outbuf, p);
362         
363         return (smb_len(outbuf)+4);
364 }
365
366 /* these are the protocol lists used for auto architecture detection:
367
368 WinNT 3.51:
369 protocol [PC NETWORK PROGRAM 1.0]
370 protocol [XENIX CORE]
371 protocol [MICROSOFT NETWORKS 1.03]
372 protocol [LANMAN1.0]
373 protocol [Windows for Workgroups 3.1a]
374 protocol [LM1.2X002]
375 protocol [LANMAN2.1]
376 protocol [NT LM 0.12]
377
378 Win95:
379 protocol [PC NETWORK PROGRAM 1.0]
380 protocol [XENIX CORE]
381 protocol [MICROSOFT NETWORKS 1.03]
382 protocol [LANMAN1.0]
383 protocol [Windows for Workgroups 3.1a]
384 protocol [LM1.2X002]
385 protocol [LANMAN2.1]
386 protocol [NT LM 0.12]
387
388 Win2K:
389 protocol [PC NETWORK PROGRAM 1.0]
390 protocol [LANMAN1.0]
391 protocol [Windows for Workgroups 3.1a]
392 protocol [LM1.2X002]
393 protocol [LANMAN2.1]
394 protocol [NT LM 0.12]
395
396 OS/2:
397 protocol [PC NETWORK PROGRAM 1.0]
398 protocol [XENIX CORE]
399 protocol [LANMAN1.0]
400 protocol [LM1.2X002]
401 protocol [LANMAN2.1]
402 */
403
404 /*
405   * Modified to recognize the architecture of the remote machine better.
406   *
407   * This appears to be the matrix of which protocol is used by which
408   * MS product.
409        Protocol                       WfWg    Win95   WinNT  Win2K  OS/2
410        PC NETWORK PROGRAM 1.0          1       1       1      1      1
411        XENIX CORE                                      2             2
412        MICROSOFT NETWORKS 3.0          2       2       
413        DOS LM1.2X002                   3       3       
414        MICROSOFT NETWORKS 1.03                         3
415        DOS LANMAN2.1                   4       4       
416        LANMAN1.0                                       4      2      3
417        Windows for Workgroups 3.1a     5       5       5      3
418        LM1.2X002                                       6      4      4
419        LANMAN2.1                                       7      5      5
420        NT LM 0.12                              6       8      6
421   *
422   *  tim@fsg.com 09/29/95
423   *  Win2K added by matty 17/7/99
424   */
425   
426 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
427 #define ARCH_WIN95    0x2
428 #define ARCH_WINNT    0x4
429 #define ARCH_WIN2K    0xC      /* Win2K is like NT */
430 #define ARCH_OS2      0x14     /* Again OS/2 is like NT */
431 #define ARCH_SAMBA    0x20
432 #define ARCH_CIFSFS   0x40
433  
434 #define ARCH_ALL      0x7F
435  
436 /* List of supported protocols, most desired first */
437 static const struct {
438         const char *proto_name;
439         const char *short_name;
440         int (*proto_reply_fn)(char *, char *);
441         int protocol_level;
442 } supported_protocols[] = {
443         {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
444         {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
445         {"POSIX 2",                 "NT1",      reply_nt1,      PROTOCOL_NT1},
446         {"LANMAN2.1",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
447         {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
448         {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
449         {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
450         {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
451         {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
452         {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
453         {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
454         {NULL,NULL,NULL,0},
455 };
456
457 /****************************************************************************
458  Reply to a negprot.
459 ****************************************************************************/
460
461 int reply_negprot(connection_struct *conn, 
462                   char *inbuf,char *outbuf, int dum_size, 
463                   int dum_buffsize)
464 {
465         int outsize = set_message(outbuf,1,0,True);
466         int Index=0;
467         int choice= -1;
468         int protocol;
469         char *p;
470         int bcc = SVAL(smb_buf(inbuf),-2);
471         int arch = ARCH_ALL;
472
473         static BOOL done_negprot = False;
474
475         START_PROFILE(SMBnegprot);
476
477         if (done_negprot) {
478                 END_PROFILE(SMBnegprot);
479                 exit_server("multiple negprot's are not permitted");
480         }
481         done_negprot = True;
482
483         p = smb_buf(inbuf)+1;
484         while (p < (smb_buf(inbuf) + bcc)) { 
485                 Index++;
486                 DEBUG(3,("Requested protocol [%s]\n",p));
487                 if (strcsequal(p,"Windows for Workgroups 3.1a"))
488                         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
489                 else if (strcsequal(p,"DOS LM1.2X002"))
490                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
491                 else if (strcsequal(p,"DOS LANMAN2.1"))
492                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
493                 else if (strcsequal(p,"NT LM 0.12"))
494                         arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K | ARCH_CIFSFS);
495                 else if (strcsequal(p,"LANMAN2.1"))
496                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
497                 else if (strcsequal(p,"LM1.2X002"))
498                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
499                 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
500                         arch &= ARCH_WINNT;
501                 else if (strcsequal(p,"XENIX CORE"))
502                         arch &= ( ARCH_WINNT | ARCH_OS2 );
503                 else if (strcsequal(p,"Samba")) {
504                         arch = ARCH_SAMBA;
505                         break;
506                 } else if (strcsequal(p,"POSIX 2")) {
507                         arch = ARCH_CIFSFS;
508                         break;
509                 }
510  
511                 p += strlen(p) + 2;
512         }
513
514         /* CIFSFS can send one arch only, NT LM 0.12. */
515         if (Index == 1 && (arch & ARCH_CIFSFS)) {
516                 arch = ARCH_CIFSFS;
517         }
518
519         switch ( arch ) {
520                 case ARCH_CIFSFS:
521                         set_remote_arch(RA_CIFSFS);
522                         break;
523                 case ARCH_SAMBA:
524                         set_remote_arch(RA_SAMBA);
525                         break;
526                 case ARCH_WFWG:
527                         set_remote_arch(RA_WFWG);
528                         break;
529                 case ARCH_WIN95:
530                         set_remote_arch(RA_WIN95);
531                         break;
532                 case ARCH_WINNT:
533                         if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
534                                 set_remote_arch(RA_WIN2K);
535                         else
536                                 set_remote_arch(RA_WINNT);
537                         break;
538                 case ARCH_WIN2K:
539                         set_remote_arch(RA_WIN2K);
540                         break;
541                 case ARCH_OS2:
542                         set_remote_arch(RA_OS2);
543                         break;
544                 default:
545                         set_remote_arch(RA_UNKNOWN);
546                 break;
547         }
548  
549         /* possibly reload - change of architecture */
550         reload_services(True);      
551         
552         /* moved from the netbios session setup code since we don't have that 
553            when the client connects to port 445.  Of course there is a small
554            window where we are listening to messages   -- jerry */
555
556         claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
557     
558         /* Check for protocols, most desirable first */
559         for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
560                 p = smb_buf(inbuf)+1;
561                 Index = 0;
562                 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
563                                 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
564                         while (p < (smb_buf(inbuf) + bcc)) { 
565                                 if (strequal(p,supported_protocols[protocol].proto_name))
566                                         choice = Index;
567                                 Index++;
568                                 p += strlen(p) + 2;
569                         }
570                 if(choice != -1)
571                         break;
572         }
573   
574         SSVAL(outbuf,smb_vwv0,choice);
575         if(choice != -1) {
576                 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
577                 reload_services(True);          
578                 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
579                 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
580         } else {
581                 DEBUG(0,("No protocol supported !\n"));
582         }
583         SSVAL(outbuf,smb_vwv0,choice);
584   
585         DEBUG( 5, ( "negprot index=%d\n", choice ) );
586
587         if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) {
588                 exit_server("SMB signing is required and client negotiated a downlevel protocol");
589         }
590
591         END_PROFILE(SMBnegprot);
592         return(outsize);
593 }