00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "includes.h"
00022
00023 extern fstring remote_proto;
00024 extern enum protocol_types Protocol;
00025 extern int max_recv;
00026
00027 BOOL global_encrypted_passwords_negotiated = False;
00028 BOOL global_spnego_negotiated = False;
00029 struct auth_context *negprot_global_auth_context = NULL;
00030
00031 static void get_challenge(char buff[8])
00032 {
00033 NTSTATUS nt_status;
00034 const uint8 *cryptkey;
00035
00036
00037
00038 if (negprot_global_auth_context) {
00039 DEBUG(3, ("get challenge: is this a secondary negprot? negprot_global_auth_context is non-NULL!\n"));
00040 (negprot_global_auth_context->free)(&negprot_global_auth_context);
00041 }
00042
00043 DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
00044 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) {
00045 DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status)));
00046 smb_panic("cannot make_negprot_global_auth_context!\n");
00047 }
00048 DEBUG(10, ("get challenge: getting challenge\n"));
00049 cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context);
00050 memcpy(buff, cryptkey, 8);
00051 }
00052
00053
00054
00055
00056
00057 static int reply_corep(char *inbuf, char *outbuf)
00058 {
00059 int outsize = set_message(outbuf,1,0,True);
00060
00061 Protocol = PROTOCOL_CORE;
00062
00063 return outsize;
00064 }
00065
00066
00067
00068
00069
00070 static int reply_coreplus(char *inbuf, char *outbuf)
00071 {
00072 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
00073 int outsize = set_message(outbuf,13,0,True);
00074 SSVAL(outbuf,smb_vwv5,raw);
00075
00076
00077 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
00078 SSVAL(outbuf,smb_vwv1,0x1);
00079
00080 Protocol = PROTOCOL_COREPLUS;
00081
00082 return outsize;
00083 }
00084
00085
00086
00087
00088
00089 static int reply_lanman1(char *inbuf, char *outbuf)
00090 {
00091 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
00092 int secword=0;
00093 time_t t = time(NULL);
00094
00095 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
00096
00097 if (lp_security()>=SEC_USER)
00098 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
00099 if (global_encrypted_passwords_negotiated)
00100 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
00101
00102 set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
00103 SSVAL(outbuf,smb_vwv1,secword);
00104
00105 if (global_encrypted_passwords_negotiated) {
00106 get_challenge(smb_buf(outbuf));
00107 SSVAL(outbuf,smb_vwv11, 8);
00108 }
00109
00110 Protocol = PROTOCOL_LANMAN1;
00111
00112
00113 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
00114 SSVAL(outbuf,smb_vwv2,max_recv);
00115 SSVAL(outbuf,smb_vwv3,lp_maxmux());
00116 SSVAL(outbuf,smb_vwv4,1);
00117 SSVAL(outbuf,smb_vwv5,raw);
00118
00119 SIVAL(outbuf,smb_vwv6,sys_getpid());
00120 SSVAL(outbuf,smb_vwv10, set_server_zone_offset(t)/60);
00121
00122 srv_put_dos_date(outbuf,smb_vwv8,t);
00123
00124 return (smb_len(outbuf)+4);
00125 }
00126
00127
00128
00129
00130
00131 static int reply_lanman2(char *inbuf, char *outbuf)
00132 {
00133 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
00134 int secword=0;
00135 time_t t = time(NULL);
00136
00137 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
00138
00139 if (lp_security()>=SEC_USER)
00140 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
00141 if (global_encrypted_passwords_negotiated)
00142 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
00143
00144 set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
00145 SSVAL(outbuf,smb_vwv1,secword);
00146 SIVAL(outbuf,smb_vwv6,sys_getpid());
00147
00148
00149 if (global_encrypted_passwords_negotiated) {
00150 get_challenge(smb_buf(outbuf));
00151 SSVAL(outbuf,smb_vwv11, 8);
00152 }
00153
00154 Protocol = PROTOCOL_LANMAN2;
00155
00156
00157 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
00158 SSVAL(outbuf,smb_vwv2,max_recv);
00159 SSVAL(outbuf,smb_vwv3,lp_maxmux());
00160 SSVAL(outbuf,smb_vwv4,1);
00161 SSVAL(outbuf,smb_vwv5,raw);
00162 SSVAL(outbuf,smb_vwv10, set_server_zone_offset(t)/60);
00163 srv_put_dos_date(outbuf,smb_vwv8,t);
00164
00165 return (smb_len(outbuf)+4);
00166 }
00167
00168
00169
00170
00171
00172 static DATA_BLOB negprot_spnego(void)
00173 {
00174 DATA_BLOB blob;
00175 nstring dos_name;
00176 fstring unix_name;
00177 #ifdef DEVELOPER
00178 size_t slen;
00179 #endif
00180 char guid[17];
00181 const char *OIDs_krb5[] = {OID_KERBEROS5,
00182 OID_KERBEROS5_OLD,
00183 OID_NTLMSSP,
00184 NULL};
00185 const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
00186
00187 global_spnego_negotiated = True;
00188
00189 memset(guid, '\0', sizeof(guid));
00190
00191 safe_strcpy(unix_name, global_myname(), sizeof(unix_name)-1);
00192 strlower_m(unix_name);
00193 push_ascii_nstring(dos_name, unix_name);
00194 safe_strcpy(guid, dos_name, sizeof(guid)-1);
00195
00196 #ifdef DEVELOPER
00197
00198 slen = strlen(dos_name);
00199 if (slen < sizeof(guid)) {
00200 memset(guid+slen, '\0', sizeof(guid) - slen);
00201 }
00202 #endif
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) {
00218 #if 0
00219
00220 blob = data_blob(guid, 16);
00221 #else
00222
00223 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
00224 #endif
00225 } else {
00226 fstring myname;
00227 char *host_princ_s = NULL;
00228 name_to_fqdn(myname, global_myname());
00229 strlower_m(myname);
00230 asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm());
00231 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s);
00232 SAFE_FREE(host_princ_s);
00233 }
00234
00235 return blob;
00236 }
00237
00238
00239
00240
00241
00242 static int reply_nt1(char *inbuf, char *outbuf)
00243 {
00244
00245 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
00246 CAP_LEVEL_II_OPLOCKS;
00247
00248 int secword=0;
00249 char *p, *q;
00250 BOOL negotiate_spnego = False;
00251 time_t t = time(NULL);
00252
00253 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
00254
00255
00256
00257
00258
00259 if ( (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY) &&
00260 ((SVAL(inbuf, smb_flg2) & FLAGS2_UNKNOWN_BIT4) == 0) )
00261 {
00262 if (get_remote_arch() != RA_SAMBA) {
00263 set_remote_arch( RA_VISTA );
00264 }
00265 }
00266
00267
00268
00269
00270 if (global_encrypted_passwords_negotiated &&
00271 (lp_security() != SEC_SHARE) &&
00272 lp_use_spnego() &&
00273 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
00274 negotiate_spnego = True;
00275 capabilities |= CAP_EXTENDED_SECURITY;
00276 add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
00277
00278
00279 SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_EXTENDED_SECURITY);
00280 }
00281
00282 capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
00283
00284 if (lp_unix_extensions()) {
00285 capabilities |= CAP_UNIX;
00286 }
00287
00288 if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
00289 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
00290
00291 if (SMB_OFF_T_BITS == 64)
00292 capabilities |= CAP_LARGE_FILES;
00293
00294 if (lp_readraw() && lp_writeraw())
00295 capabilities |= CAP_RAW_MODE;
00296
00297 if (lp_nt_status_support())
00298 capabilities |= CAP_STATUS32;
00299
00300 if (lp_host_msdfs())
00301 capabilities |= CAP_DFS;
00302
00303 if (lp_security() >= SEC_USER)
00304 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
00305 if (global_encrypted_passwords_negotiated)
00306 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
00307
00308 if (lp_server_signing()) {
00309 if (lp_security() >= SEC_USER) {
00310 secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
00311
00312 capabilities &= ~CAP_RAW_MODE;
00313 if (lp_server_signing() == Required)
00314 secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
00315 srv_set_signing_negotiated();
00316 } else {
00317 DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
00318 if (lp_server_signing() == Required) {
00319 exit_server_cleanly("reply_nt1: smb signing required and share level security selected.");
00320 }
00321 }
00322 }
00323
00324 set_message(outbuf,17,0,True);
00325
00326 SCVAL(outbuf,smb_vwv1,secword);
00327
00328 Protocol = PROTOCOL_NT1;
00329
00330 SSVAL(outbuf,smb_vwv1+1,lp_maxmux());
00331 SSVAL(outbuf,smb_vwv2+1,1);
00332 SIVAL(outbuf,smb_vwv3+1,max_recv);
00333 SIVAL(outbuf,smb_vwv5+1,0x10000);
00334 SIVAL(outbuf,smb_vwv7+1,sys_getpid());
00335 SIVAL(outbuf,smb_vwv9+1,capabilities);
00336 put_long_date(outbuf+smb_vwv11+1,t);
00337 SSVALS(outbuf,smb_vwv15+1,set_server_zone_offset(t)/60);
00338
00339 p = q = smb_buf(outbuf);
00340 if (!negotiate_spnego) {
00341
00342 if (global_encrypted_passwords_negotiated) {
00343
00344
00345 get_challenge(p);
00346 SCVAL(outbuf,smb_vwv16+1,8);
00347 p += 8;
00348 }
00349 p += srvstr_push(outbuf, p, lp_workgroup(), BUFFER_SIZE - (p-outbuf),
00350 STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
00351 DEBUG(3,("not using SPNEGO\n"));
00352 } else {
00353 DATA_BLOB spnego_blob = negprot_spnego();
00354
00355 if (spnego_blob.data == NULL) {
00356 return ERROR_NT(NT_STATUS_NO_MEMORY);
00357 }
00358
00359 memcpy(p, spnego_blob.data, spnego_blob.length);
00360 p += spnego_blob.length;
00361 data_blob_free(&spnego_blob);
00362
00363 SCVAL(outbuf,smb_vwv16+1, 0);
00364 DEBUG(3,("using SPNEGO\n"));
00365 }
00366
00367 SSVAL(outbuf,smb_vwv17, p - q);
00368 set_message_end(outbuf, p);
00369
00370 return (smb_len(outbuf)+4);
00371 }
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443 #define ARCH_WFWG 0x3
00444 #define ARCH_WIN95 0x2
00445 #define ARCH_WINNT 0x4
00446 #define ARCH_WIN2K 0xC
00447 #define ARCH_OS2 0x14
00448 #define ARCH_SAMBA 0x20
00449 #define ARCH_CIFSFS 0x40
00450 #define ARCH_VISTA 0x8C
00451
00452 #define ARCH_ALL 0x7F
00453
00454
00455 static const struct {
00456 const char *proto_name;
00457 const char *short_name;
00458 int (*proto_reply_fn)(char *, char *);
00459 int protocol_level;
00460 } supported_protocols[] = {
00461 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
00462 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
00463 {"POSIX 2", "NT1", reply_nt1, PROTOCOL_NT1},
00464 {"LANMAN2.1", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
00465 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
00466 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
00467 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
00468 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
00469 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
00470 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
00471 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
00472 {NULL,NULL,NULL,0},
00473 };
00474
00475
00476
00477
00478
00479
00480 int reply_negprot(connection_struct *conn,
00481 char *inbuf,char *outbuf, int dum_size,
00482 int dum_buffsize)
00483 {
00484 int outsize = set_message(outbuf,1,0,True);
00485 int Index=0;
00486 int choice= -1;
00487 int protocol;
00488 char *p;
00489 int bcc = SVAL(smb_buf(inbuf),-2);
00490 int arch = ARCH_ALL;
00491
00492 static BOOL done_negprot = False;
00493
00494 START_PROFILE(SMBnegprot);
00495
00496 if (done_negprot) {
00497 END_PROFILE(SMBnegprot);
00498 exit_server_cleanly("multiple negprot's are not permitted");
00499 }
00500 done_negprot = True;
00501
00502 p = smb_buf(inbuf)+1;
00503 while (p < (smb_buf(inbuf) + bcc)) {
00504 Index++;
00505 DEBUG(3,("Requested protocol [%s]\n",p));
00506 if (strcsequal(p,"Windows for Workgroups 3.1a"))
00507 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
00508 else if (strcsequal(p,"DOS LM1.2X002"))
00509 arch &= ( ARCH_WFWG | ARCH_WIN95 );
00510 else if (strcsequal(p,"DOS LANMAN2.1"))
00511 arch &= ( ARCH_WFWG | ARCH_WIN95 );
00512 else if (strcsequal(p,"NT LM 0.12"))
00513 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K | ARCH_CIFSFS);
00514 else if (strcsequal(p,"SMB 2.001"))
00515 arch = ARCH_VISTA;
00516 else if (strcsequal(p,"LANMAN2.1"))
00517 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
00518 else if (strcsequal(p,"LM1.2X002"))
00519 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
00520 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
00521 arch &= ARCH_WINNT;
00522 else if (strcsequal(p,"XENIX CORE"))
00523 arch &= ( ARCH_WINNT | ARCH_OS2 );
00524 else if (strcsequal(p,"Samba")) {
00525 arch = ARCH_SAMBA;
00526 break;
00527 } else if (strcsequal(p,"POSIX 2")) {
00528 arch = ARCH_CIFSFS;
00529 break;
00530 }
00531
00532 p += strlen(p) + 2;
00533 }
00534
00535
00536 if (Index == 1 && (arch & ARCH_CIFSFS)) {
00537 arch = ARCH_CIFSFS;
00538 }
00539
00540 switch ( arch ) {
00541 case ARCH_CIFSFS:
00542 set_remote_arch(RA_CIFSFS);
00543 break;
00544 case ARCH_SAMBA:
00545 set_remote_arch(RA_SAMBA);
00546 break;
00547 case ARCH_WFWG:
00548 set_remote_arch(RA_WFWG);
00549 break;
00550 case ARCH_WIN95:
00551 set_remote_arch(RA_WIN95);
00552 break;
00553 case ARCH_WINNT:
00554 if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
00555 set_remote_arch(RA_WIN2K);
00556 else
00557 set_remote_arch(RA_WINNT);
00558 break;
00559 case ARCH_WIN2K:
00560
00561
00562 if ( get_remote_arch() != RA_VISTA )
00563 set_remote_arch(RA_WIN2K);
00564 break;
00565 case ARCH_VISTA:
00566 set_remote_arch(RA_VISTA);
00567 break;
00568 case ARCH_OS2:
00569 set_remote_arch(RA_OS2);
00570 break;
00571 default:
00572 set_remote_arch(RA_UNKNOWN);
00573 break;
00574 }
00575
00576
00577 reload_services(True);
00578
00579
00580
00581
00582
00583 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
00584
00585
00586 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
00587 p = smb_buf(inbuf)+1;
00588 Index = 0;
00589 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
00590 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
00591 while (p < (smb_buf(inbuf) + bcc)) {
00592 if (strequal(p,supported_protocols[protocol].proto_name))
00593 choice = Index;
00594 Index++;
00595 p += strlen(p) + 2;
00596 }
00597 if(choice != -1)
00598 break;
00599 }
00600
00601 SSVAL(outbuf,smb_vwv0,choice);
00602 if(choice != -1) {
00603 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
00604 reload_services(True);
00605 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
00606 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
00607 } else {
00608 DEBUG(0,("No protocol supported !\n"));
00609 }
00610 SSVAL(outbuf,smb_vwv0,choice);
00611
00612 DEBUG( 5, ( "negprot index=%d\n", choice ) );
00613
00614 if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) {
00615 exit_server_cleanly("SMB signing is required and "
00616 "client negotiated a downlevel protocol");
00617 }
00618
00619 END_PROFILE(SMBnegprot);
00620 return(outsize);
00621 }