00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "includes.h"
00023
00024 extern pstring user_socket_options;
00025
00026 static const struct {
00027 int prot;
00028 const char *name;
00029 } prots[] = {
00030 {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
00031 {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
00032 {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
00033 {PROTOCOL_LANMAN1,"LANMAN1.0"},
00034 {PROTOCOL_LANMAN2,"LM1.2X002"},
00035 {PROTOCOL_LANMAN2,"DOS LANMAN2.1"},
00036 {PROTOCOL_LANMAN2,"LANMAN2.1"},
00037 {PROTOCOL_LANMAN2,"Samba"},
00038 {PROTOCOL_NT1,"NT LANMAN 1.0"},
00039 {PROTOCOL_NT1,"NT LM 0.12"},
00040 {-1,NULL}
00041 };
00042
00043 static const char *star_smbserver_name = "*SMBSERVER";
00044
00045
00046
00047
00048
00049
00050
00051
00052 static void cli_set_session_key (struct cli_state *cli, const DATA_BLOB session_key)
00053 {
00054 cli->user_session_key = data_blob(session_key.data, session_key.length);
00055 }
00056
00057
00058
00059
00060
00061 static NTSTATUS cli_session_setup_lanman2(struct cli_state *cli,
00062 const char *user,
00063 const char *pass, size_t passlen,
00064 const char *workgroup)
00065 {
00066 DATA_BLOB session_key = data_blob(NULL, 0);
00067 DATA_BLOB lm_response = data_blob(NULL, 0);
00068 fstring pword;
00069 char *p;
00070
00071 if (passlen > sizeof(pword)-1) {
00072 return NT_STATUS_INVALID_PARAMETER;
00073 }
00074
00075
00076
00077
00078
00079
00080 cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
00081
00082
00083 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
00084 passlen = 0;
00085
00086 if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
00087
00088 lm_response = data_blob(NULL, 24);
00089 if (!SMBencrypt(pass, cli->secblob.data,(uchar *)lm_response.data)) {
00090 DEBUG(1, ("Password is > 14 chars in length, and is therefore incompatible with Lanman authentication\n"));
00091 return NT_STATUS_ACCESS_DENIED;
00092 }
00093 } else if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen == 24) {
00094
00095 lm_response = data_blob(pass, passlen);
00096 } else if (passlen > 0) {
00097
00098 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
00099 lm_response = data_blob(pass, passlen);
00100 }
00101
00102
00103 memset(cli->outbuf,'\0',smb_size);
00104 set_message(cli->outbuf,10, 0, True);
00105 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
00106 cli_setup_packet(cli);
00107
00108 SCVAL(cli->outbuf,smb_vwv0,0xFF);
00109 SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
00110 SSVAL(cli->outbuf,smb_vwv3,2);
00111 SSVAL(cli->outbuf,smb_vwv4,1);
00112 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
00113 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
00114
00115 p = smb_buf(cli->outbuf);
00116 memcpy(p,lm_response.data,lm_response.length);
00117 p += lm_response.length;
00118 p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
00119 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
00120 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
00121 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
00122 cli_setup_bcc(cli, p);
00123
00124 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
00125 return cli_nt_error(cli);
00126 }
00127
00128 show_msg(cli->inbuf);
00129
00130 if (cli_is_error(cli)) {
00131 return cli_nt_error(cli);
00132 }
00133
00134
00135 cli->vuid = SVAL(cli->inbuf,smb_uid);
00136 fstrcpy(cli->user_name, user);
00137
00138 if (session_key.data) {
00139
00140 cli_set_session_key(cli, session_key);
00141 }
00142
00143 return NT_STATUS_OK;
00144 }
00145
00146
00147
00148
00149
00150 static uint32 cli_session_setup_capabilities(struct cli_state *cli)
00151 {
00152 uint32 capabilities = CAP_NT_SMBS;
00153
00154 if (!cli->force_dos_errors)
00155 capabilities |= CAP_STATUS32;
00156
00157 if (cli->use_level_II_oplocks)
00158 capabilities |= CAP_LEVEL_II_OPLOCKS;
00159
00160 capabilities |= (cli->capabilities & (CAP_UNICODE|CAP_LARGE_FILES|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_DFS));
00161 return capabilities;
00162 }
00163
00164
00165
00166
00167
00168 static NTSTATUS cli_session_setup_guest(struct cli_state *cli)
00169 {
00170 char *p;
00171 uint32 capabilities = cli_session_setup_capabilities(cli);
00172
00173 memset(cli->outbuf, '\0', smb_size);
00174 set_message(cli->outbuf,13,0,True);
00175 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
00176 cli_setup_packet(cli);
00177
00178 SCVAL(cli->outbuf,smb_vwv0,0xFF);
00179 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
00180 SSVAL(cli->outbuf,smb_vwv3,2);
00181 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
00182 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
00183 SSVAL(cli->outbuf,smb_vwv7,0);
00184 SSVAL(cli->outbuf,smb_vwv8,0);
00185 SIVAL(cli->outbuf,smb_vwv11,capabilities);
00186 p = smb_buf(cli->outbuf);
00187 p += clistr_push(cli, p, "", -1, STR_TERMINATE);
00188 p += clistr_push(cli, p, "", -1, STR_TERMINATE);
00189 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
00190 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
00191 cli_setup_bcc(cli, p);
00192
00193 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
00194 return cli_nt_error(cli);
00195 }
00196
00197 show_msg(cli->inbuf);
00198
00199 if (cli_is_error(cli)) {
00200 return cli_nt_error(cli);
00201 }
00202
00203 cli->vuid = SVAL(cli->inbuf,smb_uid);
00204
00205 p = smb_buf(cli->inbuf);
00206 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
00207 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
00208 p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
00209
00210 if (strstr(cli->server_type, "Samba")) {
00211 cli->is_samba = True;
00212 }
00213
00214 fstrcpy(cli->user_name, "");
00215
00216 return NT_STATUS_OK;
00217 }
00218
00219
00220
00221
00222
00223 static NTSTATUS cli_session_setup_plaintext(struct cli_state *cli,
00224 const char *user, const char *pass,
00225 const char *workgroup)
00226 {
00227 uint32 capabilities = cli_session_setup_capabilities(cli);
00228 char *p;
00229 fstring lanman;
00230
00231 fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
00232
00233 memset(cli->outbuf, '\0', smb_size);
00234 set_message(cli->outbuf,13,0,True);
00235 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
00236 cli_setup_packet(cli);
00237
00238 SCVAL(cli->outbuf,smb_vwv0,0xFF);
00239 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
00240 SSVAL(cli->outbuf,smb_vwv3,2);
00241 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
00242 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
00243 SSVAL(cli->outbuf,smb_vwv8,0);
00244 SIVAL(cli->outbuf,smb_vwv11,capabilities);
00245 p = smb_buf(cli->outbuf);
00246
00247
00248
00249 if ( (capabilities & CAP_UNICODE) == 0 ) {
00250 p += clistr_push(cli, p, pass, -1, STR_TERMINATE);
00251 SSVAL(cli->outbuf,smb_vwv7,PTR_DIFF(p, smb_buf(cli->outbuf)));
00252 } else {
00253
00254
00255
00256
00257
00258
00259
00260 p += clistr_push(cli, p, pass, -1, STR_UNICODE|STR_TERMINATE);
00261 SSVAL(cli->outbuf,smb_vwv8,PTR_DIFF(p, smb_buf(cli->outbuf))-1);
00262 }
00263
00264 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
00265 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE);
00266 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
00267 p += clistr_push(cli, p, lanman, -1, STR_TERMINATE);
00268 cli_setup_bcc(cli, p);
00269
00270 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
00271 return cli_nt_error(cli);
00272 }
00273
00274 show_msg(cli->inbuf);
00275
00276 if (cli_is_error(cli)) {
00277 return cli_nt_error(cli);
00278 }
00279
00280 cli->vuid = SVAL(cli->inbuf,smb_uid);
00281 p = smb_buf(cli->inbuf);
00282 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
00283 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
00284 p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
00285 fstrcpy(cli->user_name, user);
00286
00287 if (strstr(cli->server_type, "Samba")) {
00288 cli->is_samba = True;
00289 }
00290
00291 return NT_STATUS_OK;
00292 }
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304 static NTSTATUS cli_session_setup_nt1(struct cli_state *cli, const char *user,
00305 const char *pass, size_t passlen,
00306 const char *ntpass, size_t ntpasslen,
00307 const char *workgroup)
00308 {
00309 uint32 capabilities = cli_session_setup_capabilities(cli);
00310 DATA_BLOB lm_response = data_blob(NULL, 0);
00311 DATA_BLOB nt_response = data_blob(NULL, 0);
00312 DATA_BLOB session_key = data_blob(NULL, 0);
00313 NTSTATUS result;
00314 char *p;
00315
00316 if (passlen == 0) {
00317
00318 } else if (passlen != 24) {
00319 if (lp_client_ntlmv2_auth()) {
00320 DATA_BLOB server_chal;
00321 DATA_BLOB names_blob;
00322 server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8));
00323
00324
00325
00326
00327
00328 names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup);
00329
00330 if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal,
00331 &names_blob,
00332 &lm_response, &nt_response, &session_key)) {
00333 data_blob_free(&names_blob);
00334 data_blob_free(&server_chal);
00335 return NT_STATUS_ACCESS_DENIED;
00336 }
00337 data_blob_free(&names_blob);
00338 data_blob_free(&server_chal);
00339
00340 } else {
00341 uchar nt_hash[16];
00342 E_md4hash(pass, nt_hash);
00343
00344 #ifdef LANMAN_ONLY
00345 nt_response = data_blob(NULL, 0);
00346 #else
00347 nt_response = data_blob(NULL, 24);
00348 SMBNTencrypt(pass,cli->secblob.data,nt_response.data);
00349 #endif
00350
00351 if (lp_client_lanman_auth()) {
00352 lm_response = data_blob(NULL, 24);
00353 if (!SMBencrypt(pass,cli->secblob.data, lm_response.data)) {
00354
00355
00356 data_blob_free(&lm_response);
00357 lm_response = data_blob(nt_response.data, nt_response.length);
00358 }
00359 } else {
00360
00361 lm_response = data_blob(nt_response.data, nt_response.length);
00362 }
00363
00364 session_key = data_blob(NULL, 16);
00365 #ifdef LANMAN_ONLY
00366 E_deshash(pass, session_key.data);
00367 memset(&session_key.data[8], '\0', 8);
00368 #else
00369 SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
00370 #endif
00371 }
00372 #ifdef LANMAN_ONLY
00373 cli_simple_set_signing(cli, session_key, lm_response);
00374 #else
00375 cli_simple_set_signing(cli, session_key, nt_response);
00376 #endif
00377 } else {
00378
00379
00380
00381
00382 lm_response = data_blob(pass, passlen);
00383 nt_response = data_blob(ntpass, ntpasslen);
00384 }
00385
00386
00387 memset(cli->outbuf,'\0',smb_size);
00388
00389 set_message(cli->outbuf,13,0,True);
00390 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
00391 cli_setup_packet(cli);
00392
00393 SCVAL(cli->outbuf,smb_vwv0,0xFF);
00394 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
00395 SSVAL(cli->outbuf,smb_vwv3,2);
00396 SSVAL(cli->outbuf,smb_vwv4,cli->pid);
00397 SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
00398 SSVAL(cli->outbuf,smb_vwv7,lm_response.length);
00399 SSVAL(cli->outbuf,smb_vwv8,nt_response.length);
00400 SIVAL(cli->outbuf,smb_vwv11,capabilities);
00401 p = smb_buf(cli->outbuf);
00402 if (lm_response.length) {
00403 memcpy(p,lm_response.data, lm_response.length); p += lm_response.length;
00404 }
00405 if (nt_response.length) {
00406 memcpy(p,nt_response.data, nt_response.length); p += nt_response.length;
00407 }
00408 p += clistr_push(cli, p, user, -1, STR_TERMINATE);
00409
00410
00411 p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
00412 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
00413 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
00414 cli_setup_bcc(cli, p);
00415
00416 if (!cli_send_smb(cli) || !cli_receive_smb(cli)) {
00417 result = cli_nt_error(cli);
00418 goto end;
00419 }
00420
00421
00422
00423 if (cli_is_error(cli)) {
00424 result = cli_nt_error(cli);
00425 goto end;
00426 }
00427
00428
00429 cli->vuid = SVAL(cli->inbuf,smb_uid);
00430
00431 p = smb_buf(cli->inbuf);
00432 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
00433 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
00434 p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);
00435
00436 if (strstr(cli->server_type, "Samba")) {
00437 cli->is_samba = True;
00438 }
00439
00440 fstrcpy(cli->user_name, user);
00441
00442 if (session_key.data) {
00443
00444 cli_set_session_key(cli, session_key);
00445 }
00446
00447 result = NT_STATUS_OK;
00448 end:
00449 data_blob_free(&lm_response);
00450 data_blob_free(&nt_response);
00451 data_blob_free(&session_key);
00452 return result;
00453 }
00454
00455
00456
00457
00458
00459 static BOOL cli_session_setup_blob_send(struct cli_state *cli, DATA_BLOB blob)
00460 {
00461 uint32 capabilities = cli_session_setup_capabilities(cli);
00462 char *p;
00463
00464 capabilities |= CAP_EXTENDED_SECURITY;
00465
00466
00467 memset(cli->outbuf,'\0',smb_size);
00468
00469 set_message(cli->outbuf,12,0,True);
00470 SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
00471
00472 cli_setup_packet(cli);
00473
00474 SCVAL(cli->outbuf,smb_vwv0,0xFF);
00475 SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
00476 SSVAL(cli->outbuf,smb_vwv3,2);
00477 SSVAL(cli->outbuf,smb_vwv4,1);
00478 SIVAL(cli->outbuf,smb_vwv5,0);
00479 SSVAL(cli->outbuf,smb_vwv7,blob.length);
00480 SIVAL(cli->outbuf,smb_vwv10,capabilities);
00481 p = smb_buf(cli->outbuf);
00482 memcpy(p, blob.data, blob.length);
00483 p += blob.length;
00484 p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
00485 p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
00486 cli_setup_bcc(cli, p);
00487 return cli_send_smb(cli);
00488 }
00489
00490
00491
00492
00493
00494 static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli)
00495 {
00496 DATA_BLOB blob2 = data_blob(NULL, 0);
00497 char *p;
00498 size_t len;
00499
00500 if (!cli_receive_smb(cli))
00501 return blob2;
00502
00503 show_msg(cli->inbuf);
00504
00505 if (cli_is_error(cli) && !NT_STATUS_EQUAL(cli_nt_error(cli),
00506 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
00507 return blob2;
00508 }
00509
00510
00511 cli->vuid = SVAL(cli->inbuf,smb_uid);
00512
00513 p = smb_buf(cli->inbuf);
00514
00515 blob2 = data_blob(p, SVAL(cli->inbuf, smb_vwv3));
00516
00517 p += blob2.length;
00518 p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
00519
00520
00521 len = smb_buflen(cli->inbuf) - PTR_DIFF(p, smb_buf(cli->inbuf));
00522 p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), len, 0);
00523
00524 return blob2;
00525 }
00526
00527 #ifdef HAVE_KRB5
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539 #define BASE_SESSSETUP_BLOB_PACKET_SIZE (35 + 24 + 22)
00540
00541 static BOOL cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob, DATA_BLOB session_key_krb5)
00542 {
00543 int32 remaining = blob.length;
00544 int32 cur = 0;
00545 DATA_BLOB send_blob = data_blob(NULL, 0);
00546 int32 max_blob_size = 0;
00547 DATA_BLOB receive_blob = data_blob(NULL, 0);
00548
00549 if (cli->max_xmit < BASE_SESSSETUP_BLOB_PACKET_SIZE + 1) {
00550 DEBUG(0,("cli_session_setup_blob: cli->max_xmit too small "
00551 "(was %u, need minimum %u)\n",
00552 (unsigned int)cli->max_xmit,
00553 BASE_SESSSETUP_BLOB_PACKET_SIZE));
00554 cli_set_nt_error(cli, NT_STATUS_INVALID_PARAMETER);
00555 return False;
00556 }
00557
00558 max_blob_size = cli->max_xmit - BASE_SESSSETUP_BLOB_PACKET_SIZE;
00559
00560 while ( remaining > 0) {
00561 if (remaining >= max_blob_size) {
00562 send_blob.length = max_blob_size;
00563 remaining -= max_blob_size;
00564 } else {
00565 DATA_BLOB null_blob = data_blob(NULL, 0);
00566
00567 send_blob.length = remaining;
00568 remaining = 0;
00569
00570
00571 cli_simple_set_signing(cli, session_key_krb5, null_blob);
00572 }
00573
00574 send_blob.data = &blob.data[cur];
00575 cur += send_blob.length;
00576
00577 DEBUG(10, ("cli_session_setup_blob: Remaining (%u) sending (%u) current (%u)\n",
00578 (unsigned int)remaining,
00579 (unsigned int)send_blob.length,
00580 (unsigned int)cur ));
00581
00582 if (!cli_session_setup_blob_send(cli, send_blob)) {
00583 DEBUG(0, ("cli_session_setup_blob: send failed\n"));
00584 return False;
00585 }
00586
00587 receive_blob = cli_session_setup_blob_receive(cli);
00588 data_blob_free(&receive_blob);
00589
00590 if (cli_is_error(cli) &&
00591 !NT_STATUS_EQUAL( cli_get_nt_error(cli),
00592 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
00593 DEBUG(0, ("cli_session_setup_blob: recieve failed (%s)\n",
00594 nt_errstr(cli_get_nt_error(cli)) ));
00595 cli->vuid = 0;
00596 return False;
00597 }
00598 }
00599
00600 return True;
00601 }
00602
00603
00604
00605
00606
00607 static void use_in_memory_ccache(void) {
00608 setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1);
00609 }
00610
00611
00612
00613
00614
00615 static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
00616 {
00617 DATA_BLOB negTokenTarg;
00618 DATA_BLOB session_key_krb5;
00619 int rc;
00620
00621 DEBUG(2,("Doing kerberos session setup\n"));
00622
00623
00624 rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0, NULL);
00625
00626 if (rc) {
00627 DEBUG(1, ("cli_session_setup_kerberos: spnego_gen_negTokenTarg failed: %s\n",
00628 error_message(rc)));
00629 return ADS_ERROR_KRB5(rc);
00630 }
00631
00632 #if 0
00633 file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
00634 #endif
00635
00636 if (!cli_session_setup_blob(cli, negTokenTarg, session_key_krb5)) {
00637 data_blob_free(&negTokenTarg);
00638 data_blob_free(&session_key_krb5);
00639 return ADS_ERROR_NT(cli_nt_error(cli));
00640 }
00641
00642 cli_set_session_key(cli, session_key_krb5);
00643
00644 data_blob_free(&negTokenTarg);
00645 data_blob_free(&session_key_krb5);
00646
00647 if (cli_is_error(cli)) {
00648 if (NT_STATUS_IS_OK(cli_nt_error(cli))) {
00649 return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
00650 }
00651 }
00652 return ADS_ERROR_NT(cli_nt_error(cli));
00653 }
00654 #endif
00655
00656
00657
00658
00659
00660
00661 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user,
00662 const char *pass, const char *domain)
00663 {
00664 struct ntlmssp_state *ntlmssp_state;
00665 NTSTATUS nt_status;
00666 int turn = 1;
00667 DATA_BLOB msg1;
00668 DATA_BLOB blob = data_blob(NULL, 0);
00669 DATA_BLOB blob_in = data_blob(NULL, 0);
00670 DATA_BLOB blob_out = data_blob(NULL, 0);
00671
00672 cli_temp_set_signing(cli);
00673
00674 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) {
00675 return nt_status;
00676 }
00677 ntlmssp_want_feature(ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
00678
00679 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
00680 return nt_status;
00681 }
00682 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
00683 return nt_status;
00684 }
00685 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
00686 return nt_status;
00687 }
00688
00689 do {
00690 nt_status = ntlmssp_update(ntlmssp_state,
00691 blob_in, &blob_out);
00692 data_blob_free(&blob_in);
00693 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) {
00694 if (turn == 1) {
00695
00696 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
00697 } else {
00698
00699 msg1 = spnego_gen_auth(blob_out);
00700 }
00701
00702
00703 if (!cli_session_setup_blob_send(cli, msg1)) {
00704 DEBUG(3, ("Failed to send NTLMSSP/SPNEGO blob to server!\n"));
00705 nt_status = NT_STATUS_UNSUCCESSFUL;
00706 } else {
00707 blob = cli_session_setup_blob_receive(cli);
00708
00709 nt_status = cli_nt_error(cli);
00710 if (cli_is_error(cli) && NT_STATUS_IS_OK(nt_status)) {
00711 if (cli->smb_rw_error == READ_BAD_SIG) {
00712 nt_status = NT_STATUS_ACCESS_DENIED;
00713 } else {
00714 nt_status = NT_STATUS_UNSUCCESSFUL;
00715 }
00716 }
00717 }
00718 data_blob_free(&msg1);
00719 }
00720
00721 if (!blob.length) {
00722 if (NT_STATUS_IS_OK(nt_status)) {
00723 nt_status = NT_STATUS_UNSUCCESSFUL;
00724 }
00725 } else if ((turn == 1) &&
00726 NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
00727 DATA_BLOB tmp_blob = data_blob(NULL, 0);
00728
00729 if (!spnego_parse_challenge(blob, &blob_in,
00730 &tmp_blob)) {
00731 DEBUG(3,("Failed to parse challenges\n"));
00732 nt_status = NT_STATUS_INVALID_PARAMETER;
00733 }
00734 data_blob_free(&tmp_blob);
00735 } else {
00736 if (!spnego_parse_auth_response(blob, nt_status,
00737 &blob_in)) {
00738 DEBUG(3,("Failed to parse auth response\n"));
00739 if (NT_STATUS_IS_OK(nt_status)
00740 || NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED))
00741 nt_status = NT_STATUS_INVALID_PARAMETER;
00742 }
00743 }
00744 data_blob_free(&blob);
00745 data_blob_free(&blob_out);
00746 turn++;
00747 } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED));
00748
00749 data_blob_free(&blob_in);
00750
00751 if (NT_STATUS_IS_OK(nt_status)) {
00752
00753 DATA_BLOB key = data_blob(ntlmssp_state->session_key.data,
00754 ntlmssp_state->session_key.length);
00755 DATA_BLOB null_blob = data_blob(NULL, 0);
00756 BOOL res;
00757
00758 fstrcpy(cli->server_domain, ntlmssp_state->server_domain);
00759 cli_set_session_key(cli, ntlmssp_state->session_key);
00760
00761 res = cli_simple_set_signing(cli, key, null_blob);
00762
00763 data_blob_free(&key);
00764
00765 if (res) {
00766
00767
00768
00769 cli_calculate_sign_mac(cli);
00770
00771 if (!cli_check_sign_mac(cli)) {
00772 nt_status = NT_STATUS_ACCESS_DENIED;
00773 }
00774 }
00775 }
00776
00777
00778
00779
00780 ntlmssp_end(&ntlmssp_state);
00781
00782 if (!NT_STATUS_IS_OK(nt_status)) {
00783 cli->vuid = 0;
00784 }
00785 return nt_status;
00786 }
00787
00788
00789
00790
00791
00792
00793
00794
00795 ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
00796 const char *pass, const char *user_domain,
00797 const char * dest_realm)
00798 {
00799 char *principal = NULL;
00800 char *OIDs[ASN1_MAX_OIDS];
00801 int i;
00802 BOOL got_kerberos_mechanism = False;
00803 DATA_BLOB blob;
00804
00805 DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length));
00806
00807
00808 if (cli->secblob.length <= 16) {
00809 DEBUG(3,("server didn't supply a full spnego negprot\n"));
00810 goto ntlmssp;
00811 }
00812
00813 #if 0
00814 file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
00815 #endif
00816
00817
00818 blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
00819
00820
00821
00822
00823
00824 if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
00825 data_blob_free(&blob);
00826 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
00827 }
00828 data_blob_free(&blob);
00829
00830
00831 for (i=0;OIDs[i];i++) {
00832 DEBUG(3,("got OID=%s\n", OIDs[i]));
00833 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
00834 strcmp(OIDs[i], OID_KERBEROS5) == 0) {
00835 got_kerberos_mechanism = True;
00836 }
00837 free(OIDs[i]);
00838 }
00839
00840 DEBUG(3,("got principal=%s\n", principal ? principal : "<null>"));
00841
00842 fstrcpy(cli->user_name, user);
00843
00844 #ifdef HAVE_KRB5
00845
00846
00847
00848 if (got_kerberos_mechanism && cli->use_kerberos) {
00849 ADS_STATUS rc;
00850
00851 if (pass && *pass) {
00852 int ret;
00853
00854 use_in_memory_ccache();
00855 ret = kerberos_kinit_password(user, pass, 0 , NULL);
00856
00857 if (ret){
00858 SAFE_FREE(principal);
00859 DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
00860 if (cli->fallback_after_kerberos)
00861 goto ntlmssp;
00862 return ADS_ERROR_KRB5(ret);
00863 }
00864 }
00865
00866
00867
00868
00869 if (strequal(principal, ADS_IGNORE_PRINCIPAL)) {
00870 SAFE_FREE(principal);
00871 }
00872 if (principal == NULL &&
00873 !is_ipaddress(cli->desthost) &&
00874 !strequal(star_smbserver_name,
00875 cli->desthost)) {
00876 char *realm = NULL;
00877 char *machine = NULL;
00878 char *host = NULL;
00879 DEBUG(3,("cli_session_setup_spnego: got a "
00880 "bad server principal, trying to guess ...\n"));
00881
00882 host = strchr_m(cli->desthost, '.');
00883 if (host) {
00884 machine = SMB_STRNDUP(cli->desthost,
00885 host - cli->desthost);
00886 } else {
00887 machine = SMB_STRDUP(cli->desthost);
00888 }
00889 if (machine == NULL) {
00890 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
00891 }
00892
00893 if (dest_realm) {
00894 realm = SMB_STRDUP(dest_realm);
00895 strupper_m(realm);
00896 } else {
00897 realm = kerberos_get_default_realm_from_ccache();
00898 }
00899 if (realm && *realm) {
00900 if (asprintf(&principal, "%s$@%s",
00901 machine, realm) < 0) {
00902 SAFE_FREE(machine);
00903 SAFE_FREE(realm);
00904 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
00905 }
00906 DEBUG(3,("cli_session_setup_spnego: guessed "
00907 "server principal=%s\n",
00908 principal ? principal : "<null>"));
00909 }
00910 SAFE_FREE(machine);
00911 SAFE_FREE(realm);
00912 }
00913
00914 if (principal) {
00915 rc = cli_session_setup_kerberos(cli, principal,
00916 dest_realm);
00917 if (ADS_ERR_OK(rc) || !cli->fallback_after_kerberos) {
00918 SAFE_FREE(principal);
00919 return rc;
00920 }
00921 }
00922 }
00923 #endif
00924
00925 SAFE_FREE(principal);
00926
00927 ntlmssp:
00928
00929 return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, user, pass,
00930 user_domain));
00931 }
00932
00933
00934
00935
00936
00937
00938
00939 NTSTATUS cli_session_setup(struct cli_state *cli,
00940 const char *user,
00941 const char *pass, int passlen,
00942 const char *ntpass, int ntpasslen,
00943 const char *workgroup)
00944 {
00945 char *p;
00946 fstring user2;
00947
00948
00949 fstrcpy(user2, user);
00950 if ((p=strchr_m(user2,'\\')) || (p=strchr_m(user2,'/')) ||
00951 (p=strchr_m(user2,*lp_winbind_separator()))) {
00952 *p = 0;
00953 user = p+1;
00954 workgroup = user2;
00955 }
00956
00957 if (cli->protocol < PROTOCOL_LANMAN1) {
00958 return NT_STATUS_OK;
00959 }
00960
00961
00962
00963
00964
00965
00966
00967 if (cli->protocol < PROTOCOL_NT1) {
00968 if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) {
00969 DEBUG(1, ("Server requested LM password but 'client lanman auth'"
00970 " is disabled\n"));
00971 return NT_STATUS_ACCESS_DENIED;
00972 }
00973
00974 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 &&
00975 !lp_client_plaintext_auth() && (*pass)) {
00976 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
00977 " is disabled\n"));
00978 return NT_STATUS_ACCESS_DENIED;
00979 }
00980
00981 return cli_session_setup_lanman2(cli, user, pass, passlen,
00982 workgroup);
00983 }
00984
00985
00986
00987
00988 if (!user || !*user)
00989 return cli_session_setup_guest(cli);
00990
00991
00992
00993
00994
00995 if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
00996 return cli_session_setup_plaintext(cli, user, "", workgroup);
00997
00998
00999
01000
01001 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
01002 if (!lp_client_plaintext_auth() && (*pass)) {
01003 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
01004 " is disabled\n"));
01005 return NT_STATUS_ACCESS_DENIED;
01006 }
01007 return cli_session_setup_plaintext(cli, user, pass, workgroup);
01008 }
01009
01010
01011
01012 if (cli->capabilities & CAP_EXTENDED_SECURITY) {
01013 ADS_STATUS status = cli_session_setup_spnego(cli, user, pass,
01014 workgroup, NULL);
01015 if (!ADS_ERR_OK(status)) {
01016 DEBUG(3, ("SPNEGO login failed: %s\n", ads_errstr(status)));
01017 return ads_ntstatus(status);
01018 }
01019 } else {
01020 NTSTATUS status;
01021
01022
01023 status = cli_session_setup_nt1(cli, user, pass, passlen,
01024 ntpass, ntpasslen, workgroup);
01025 if (!NT_STATUS_IS_OK(status)) {
01026 DEBUG(3,("cli_session_setup: NT1 session setup "
01027 "failed: %s\n", nt_errstr(status)));
01028 return status;
01029 }
01030 }
01031
01032 if (strstr(cli->server_type, "Samba")) {
01033 cli->is_samba = True;
01034 }
01035
01036 return NT_STATUS_OK;
01037 }
01038
01039
01040
01041
01042
01043 BOOL cli_ulogoff(struct cli_state *cli)
01044 {
01045 memset(cli->outbuf,'\0',smb_size);
01046 set_message(cli->outbuf,2,0,True);
01047 SCVAL(cli->outbuf,smb_com,SMBulogoffX);
01048 cli_setup_packet(cli);
01049 SSVAL(cli->outbuf,smb_vwv0,0xFF);
01050 SSVAL(cli->outbuf,smb_vwv2,0);
01051
01052 cli_send_smb(cli);
01053 if (!cli_receive_smb(cli))
01054 return False;
01055
01056 if (cli_is_error(cli)) {
01057 return False;
01058 }
01059
01060 cli->cnum = -1;
01061 return True;
01062 }
01063
01064
01065
01066
01067
01068 BOOL cli_send_tconX(struct cli_state *cli,
01069 const char *share, const char *dev, const char *pass, int passlen)
01070 {
01071 fstring fullshare, pword;
01072 char *p;
01073 memset(cli->outbuf,'\0',smb_size);
01074 memset(cli->inbuf,'\0',smb_size);
01075
01076 fstrcpy(cli->share, share);
01077
01078
01079 if (cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) {
01080 passlen = 1;
01081 pass = "";
01082 } else if (!pass) {
01083 DEBUG(1, ("Server not using user level security and no password supplied.\n"));
01084 return False;
01085 }
01086
01087 if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) &&
01088 *pass && passlen != 24) {
01089 if (!lp_client_lanman_auth()) {
01090 DEBUG(1, ("Server requested LANMAN password (share-level security) but 'client use lanman auth'"
01091 " is disabled\n"));
01092 return False;
01093 }
01094
01095
01096
01097
01098 passlen = 24;
01099 SMBencrypt(pass,cli->secblob.data,(uchar *)pword);
01100 } else {
01101 if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) == 0) {
01102 if (!lp_client_plaintext_auth() && (*pass)) {
01103 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
01104 " is disabled\n"));
01105 return False;
01106 }
01107
01108
01109
01110
01111 passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE);
01112
01113 } else {
01114 if (passlen) {
01115 memcpy(pword, pass, passlen);
01116 }
01117 }
01118 }
01119
01120 slprintf(fullshare, sizeof(fullshare)-1,
01121 "\\\\%s\\%s", cli->desthost, share);
01122
01123 set_message(cli->outbuf,4, 0, True);
01124 SCVAL(cli->outbuf,smb_com,SMBtconX);
01125 cli_setup_packet(cli);
01126
01127 SSVAL(cli->outbuf,smb_vwv0,0xFF);
01128 SSVAL(cli->outbuf,smb_vwv2,TCONX_FLAG_EXTENDED_RESPONSE);
01129 SSVAL(cli->outbuf,smb_vwv3,passlen);
01130
01131 p = smb_buf(cli->outbuf);
01132 if (passlen) {
01133 memcpy(p,pword,passlen);
01134 }
01135 p += passlen;
01136 p += clistr_push(cli, p, fullshare, -1, STR_TERMINATE |STR_UPPER);
01137 p += clistr_push(cli, p, dev, -1, STR_TERMINATE |STR_UPPER | STR_ASCII);
01138
01139 cli_setup_bcc(cli, p);
01140
01141 cli_send_smb(cli);
01142 if (!cli_receive_smb(cli))
01143 return False;
01144
01145 if (cli_is_error(cli))
01146 return False;
01147
01148 clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE|STR_ASCII);
01149
01150 if (cli->protocol >= PROTOCOL_NT1 &&
01151 smb_buflen(cli->inbuf) == 3) {
01152
01153 cli->win95 = True;
01154 }
01155
01156
01157
01158
01159 cli->dfsroot = False;
01160 if ( (CVAL(cli->inbuf, smb_wct))>2 && cli->protocol >= PROTOCOL_LANMAN2 )
01161 cli->dfsroot = (SVAL( cli->inbuf, smb_vwv2 ) & SMB_SHARE_IN_DFS) ? True : False;
01162
01163 cli->cnum = SVAL(cli->inbuf,smb_tid);
01164 return True;
01165 }
01166
01167
01168
01169
01170
01171 BOOL cli_tdis(struct cli_state *cli)
01172 {
01173 memset(cli->outbuf,'\0',smb_size);
01174 set_message(cli->outbuf,0,0,True);
01175 SCVAL(cli->outbuf,smb_com,SMBtdis);
01176 SSVAL(cli->outbuf,smb_tid,cli->cnum);
01177 cli_setup_packet(cli);
01178
01179 cli_send_smb(cli);
01180 if (!cli_receive_smb(cli))
01181 return False;
01182
01183 if (cli_is_error(cli)) {
01184 return False;
01185 }
01186
01187 cli->cnum = -1;
01188 return True;
01189 }
01190
01191
01192
01193
01194
01195 void cli_negprot_send(struct cli_state *cli)
01196 {
01197 char *p;
01198 int numprots;
01199
01200 if (cli->protocol < PROTOCOL_NT1)
01201 cli->use_spnego = False;
01202
01203 memset(cli->outbuf,'\0',smb_size);
01204
01205
01206 set_message(cli->outbuf,0,0,True);
01207
01208 p = smb_buf(cli->outbuf);
01209 for (numprots=0;
01210 prots[numprots].name && prots[numprots].prot<=cli->protocol;
01211 numprots++) {
01212 *p++ = 2;
01213 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
01214 }
01215
01216 SCVAL(cli->outbuf,smb_com,SMBnegprot);
01217 cli_setup_bcc(cli, p);
01218 cli_setup_packet(cli);
01219
01220 SCVAL(smb_buf(cli->outbuf),0,2);
01221
01222 cli_send_smb(cli);
01223 }
01224
01225
01226
01227
01228
01229 BOOL cli_negprot(struct cli_state *cli)
01230 {
01231 char *p;
01232 int numprots;
01233 int plength;
01234
01235 if (cli->protocol < PROTOCOL_NT1)
01236 cli->use_spnego = False;
01237
01238 memset(cli->outbuf,'\0',smb_size);
01239
01240
01241 for (plength=0,numprots=0;
01242 prots[numprots].name && prots[numprots].prot<=cli->protocol;
01243 numprots++)
01244 plength += strlen(prots[numprots].name)+2;
01245
01246 set_message(cli->outbuf,0,plength,True);
01247
01248 p = smb_buf(cli->outbuf);
01249 for (numprots=0;
01250 prots[numprots].name && prots[numprots].prot<=cli->protocol;
01251 numprots++) {
01252 *p++ = 2;
01253 p += clistr_push(cli, p, prots[numprots].name, -1, STR_TERMINATE);
01254 }
01255
01256 SCVAL(cli->outbuf,smb_com,SMBnegprot);
01257 cli_setup_packet(cli);
01258
01259 SCVAL(smb_buf(cli->outbuf),0,2);
01260
01261 cli_send_smb(cli);
01262 if (!cli_receive_smb(cli))
01263 return False;
01264
01265 show_msg(cli->inbuf);
01266
01267 if (cli_is_error(cli) ||
01268 ((int)SVAL(cli->inbuf,smb_vwv0) >= numprots)) {
01269 return(False);
01270 }
01271
01272 cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
01273
01274 if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) {
01275 DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n"));
01276 return False;
01277 }
01278
01279 if (cli->protocol >= PROTOCOL_NT1) {
01280 struct timespec ts;
01281
01282 cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
01283 cli->max_mux = SVAL(cli->inbuf, smb_vwv1+1);
01284 cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
01285 cli->sesskey = IVAL(cli->inbuf,smb_vwv7+1);
01286 cli->serverzone = SVALS(cli->inbuf,smb_vwv15+1);
01287 cli->serverzone *= 60;
01288
01289 ts = interpret_long_date(cli->inbuf+smb_vwv11+1);
01290 cli->servertime = ts.tv_sec;
01291 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
01292 cli->capabilities = IVAL(cli->inbuf,smb_vwv9+1);
01293 if (cli->capabilities & CAP_RAW_MODE) {
01294 cli->readbraw_supported = True;
01295 cli->writebraw_supported = True;
01296 }
01297
01298 if (!(cli->capabilities & CAP_EXTENDED_SECURITY) &&
01299 smb_buflen(cli->inbuf) > 8) {
01300 clistr_pull(cli, cli->server_domain,
01301 smb_buf(cli->inbuf)+8, sizeof(cli->server_domain),
01302 smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
01303 }
01304
01305
01306
01307
01308
01309
01310 if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) {
01311
01312 if (!cli->sign_info.allow_smb_signing) {
01313 DEBUG(0,("cli_negprot: SMB signing is mandatory and we have disabled it.\n"));
01314 return False;
01315 }
01316 cli->sign_info.negotiated_smb_signing = True;
01317 cli->sign_info.mandatory_signing = True;
01318 } else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) {
01319
01320 if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) {
01321 DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n"));
01322 return False;
01323 }
01324 cli->sign_info.negotiated_smb_signing = True;
01325 cli->sign_info.mandatory_signing = True;
01326 } else if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
01327 cli->sign_info.negotiated_smb_signing = True;
01328 }
01329
01330 if (cli->capabilities & (CAP_LARGE_READX|CAP_LARGE_WRITEX)) {
01331 SAFE_FREE(cli->outbuf);
01332 SAFE_FREE(cli->inbuf);
01333 cli->outbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
01334 cli->inbuf = (char *)SMB_MALLOC(CLI_SAMBA_MAX_LARGE_READX_SIZE+LARGE_WRITEX_HDR_SIZE+SAFETY_MARGIN);
01335 cli->bufsize = CLI_SAMBA_MAX_LARGE_READX_SIZE + LARGE_WRITEX_HDR_SIZE;
01336 }
01337
01338 } else if (cli->protocol >= PROTOCOL_LANMAN1) {
01339 cli->use_spnego = False;
01340 cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
01341 cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
01342 cli->max_mux = SVAL(cli->inbuf, smb_vwv3);
01343 cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
01344 cli->serverzone = SVALS(cli->inbuf,smb_vwv10);
01345 cli->serverzone *= 60;
01346
01347 cli->servertime = cli_make_unix_date(cli,cli->inbuf+smb_vwv8);
01348 cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
01349 cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
01350 cli->secblob = data_blob(smb_buf(cli->inbuf),smb_buflen(cli->inbuf));
01351 } else {
01352
01353 cli->use_spnego = False;
01354 cli->sec_mode = 0;
01355 cli->serverzone = get_time_zone(time(NULL));
01356 }
01357
01358 cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
01359
01360
01361 if (getenv("CLI_FORCE_ASCII"))
01362 cli->capabilities &= ~CAP_UNICODE;
01363
01364 return True;
01365 }
01366
01367
01368
01369
01370
01371 BOOL cli_session_request(struct cli_state *cli,
01372 struct nmb_name *calling, struct nmb_name *called)
01373 {
01374 char *p;
01375 int len = 4;
01376
01377 memcpy(&(cli->calling), calling, sizeof(*calling));
01378 memcpy(&(cli->called ), called , sizeof(*called ));
01379
01380
01381 p = cli->outbuf+len;
01382 name_mangle(cli->called .name, p, cli->called .name_type);
01383 len += name_len(p);
01384
01385
01386 p = cli->outbuf+len;
01387 name_mangle(cli->calling.name, p, cli->calling.name_type);
01388 len += name_len(p);
01389
01390
01391 if (cli->port == 445)
01392 return True;
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402 len -= 4;
01403 _smb_setlen(cli->outbuf,len);
01404 SCVAL(cli->outbuf,0,0x81);
01405
01406 cli_send_smb(cli);
01407 DEBUG(5,("Sent session request\n"));
01408
01409 if (!cli_receive_smb(cli))
01410 return False;
01411
01412 if (CVAL(cli->inbuf,0) == 0x84) {
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424 int port = (CVAL(cli->inbuf,8)<<8)+CVAL(cli->inbuf,9);
01425
01426 putip((char *)&cli->dest_ip,cli->inbuf+4);
01427
01428 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, port, LONG_CONNECT_TIMEOUT);
01429 if (cli->fd == -1)
01430 return False;
01431
01432 DEBUG(3,("Retargeted\n"));
01433
01434 set_socket_options(cli->fd,user_socket_options);
01435
01436
01437 {
01438 static int depth;
01439 BOOL ret;
01440 if (depth > 4) {
01441 DEBUG(0,("Retarget recursion - failing\n"));
01442 return False;
01443 }
01444 depth++;
01445 ret = cli_session_request(cli, calling, called);
01446 depth--;
01447 return ret;
01448 }
01449 }
01450
01451 if (CVAL(cli->inbuf,0) != 0x82) {
01452
01453 cli->rap_error = CVAL(cli->inbuf,4);
01454 return False;
01455 }
01456 return(True);
01457 }
01458
01459
01460
01461
01462
01463 NTSTATUS cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
01464 {
01465 int name_type = 0x20;
01466 char *p;
01467
01468
01469 if (!host) host = star_smbserver_name;
01470
01471 fstrcpy(cli->desthost, host);
01472
01473
01474 if ((p = strchr(cli->desthost, '#'))) {
01475 name_type = strtol(p+1, NULL, 16);
01476 *p = 0;
01477 }
01478
01479 if (!ip || is_zero_ip(*ip)) {
01480 if (!resolve_name(cli->desthost, &cli->dest_ip, name_type)) {
01481 return NT_STATUS_BAD_NETWORK_NAME;
01482 }
01483 if (ip) *ip = cli->dest_ip;
01484 } else {
01485 cli->dest_ip = *ip;
01486 }
01487
01488 if (getenv("LIBSMB_PROG")) {
01489 cli->fd = sock_exec(getenv("LIBSMB_PROG"));
01490 } else {
01491
01492 int port = cli->port?cli->port:445;
01493 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
01494 port, cli->timeout);
01495 if (cli->fd == -1 && cli->port == 0) {
01496 port = 139;
01497 cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip,
01498 port, cli->timeout);
01499 }
01500 if (cli->fd != -1)
01501 cli->port = port;
01502 }
01503 if (cli->fd == -1) {
01504 DEBUG(1,("Error connecting to %s (%s)\n",
01505 ip?inet_ntoa(*ip):host,strerror(errno)));
01506 return map_nt_error_from_unix(errno);
01507 }
01508
01509 set_socket_options(cli->fd,user_socket_options);
01510
01511 return NT_STATUS_OK;
01512 }
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523 NTSTATUS cli_start_connection(struct cli_state **output_cli,
01524 const char *my_name,
01525 const char *dest_host,
01526 struct in_addr *dest_ip, int port,
01527 int signing_state, int flags,
01528 BOOL *retry)
01529 {
01530 NTSTATUS nt_status;
01531 struct nmb_name calling;
01532 struct nmb_name called;
01533 struct cli_state *cli;
01534 struct in_addr ip;
01535
01536 if (retry)
01537 *retry = False;
01538
01539 if (!my_name)
01540 my_name = global_myname();
01541
01542 if (!(cli = cli_initialise())) {
01543 return NT_STATUS_NO_MEMORY;
01544 }
01545
01546 make_nmb_name(&calling, my_name, 0x0);
01547 make_nmb_name(&called , dest_host, 0x20);
01548
01549 if (cli_set_port(cli, port) != port) {
01550 cli_shutdown(cli);
01551 return NT_STATUS_UNSUCCESSFUL;
01552 }
01553
01554 cli_set_timeout(cli, 10000);
01555
01556 if (dest_ip)
01557 ip = *dest_ip;
01558 else
01559 ZERO_STRUCT(ip);
01560
01561 again:
01562
01563 DEBUG(3,("Connecting to host=%s\n", dest_host));
01564
01565 nt_status = cli_connect(cli, dest_host, &ip);
01566 if (!NT_STATUS_IS_OK(nt_status)) {
01567 DEBUG(1,("cli_start_connection: failed to connect to %s (%s). Error %s\n",
01568 nmb_namestr(&called), inet_ntoa(ip), nt_errstr(nt_status) ));
01569 cli_shutdown(cli);
01570 return nt_status;
01571 }
01572
01573 if (retry)
01574 *retry = True;
01575
01576 if (!cli_session_request(cli, &calling, &called)) {
01577 char *p;
01578 DEBUG(1,("session request to %s failed (%s)\n",
01579 called.name, cli_errstr(cli)));
01580 if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
01581 *p = 0;
01582 goto again;
01583 }
01584 if (strcmp(called.name, star_smbserver_name)) {
01585 make_nmb_name(&called , star_smbserver_name, 0x20);
01586 goto again;
01587 }
01588 return NT_STATUS_BAD_NETWORK_NAME;
01589 }
01590
01591 cli_setup_signing_state(cli, signing_state);
01592
01593 if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
01594 cli->use_spnego = False;
01595 else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
01596 cli->use_kerberos = True;
01597
01598 if (!cli_negprot(cli)) {
01599 DEBUG(1,("failed negprot\n"));
01600 nt_status = cli_nt_error(cli);
01601 if (NT_STATUS_IS_OK(nt_status)) {
01602 nt_status = NT_STATUS_UNSUCCESSFUL;
01603 }
01604 cli_shutdown(cli);
01605 return nt_status;
01606 }
01607
01608 *output_cli = cli;
01609 return NT_STATUS_OK;
01610 }
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627 NTSTATUS cli_full_connection(struct cli_state **output_cli,
01628 const char *my_name,
01629 const char *dest_host,
01630 struct in_addr *dest_ip, int port,
01631 const char *service, const char *service_type,
01632 const char *user, const char *domain,
01633 const char *password, int flags,
01634 int signing_state,
01635 BOOL *retry)
01636 {
01637 NTSTATUS nt_status;
01638 struct cli_state *cli = NULL;
01639 int pw_len = password ? strlen(password)+1 : 0;
01640
01641 *output_cli = NULL;
01642
01643 if (password == NULL) {
01644 password = "";
01645 }
01646
01647 nt_status = cli_start_connection(&cli, my_name, dest_host,
01648 dest_ip, port, signing_state, flags, retry);
01649
01650 if (!NT_STATUS_IS_OK(nt_status)) {
01651 return nt_status;
01652 }
01653
01654 nt_status = cli_session_setup(cli, user, password, pw_len, password,
01655 pw_len, domain);
01656 if (!NT_STATUS_IS_OK(nt_status)) {
01657
01658 if (!(flags & CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK)) {
01659 DEBUG(1,("failed session setup with %s\n",
01660 nt_errstr(nt_status)));
01661 cli_shutdown(cli);
01662 return nt_status;
01663 }
01664
01665 nt_status = cli_session_setup(cli, "", "", 0, "", 0, domain);
01666 if (!NT_STATUS_IS_OK(nt_status)) {
01667 DEBUG(1,("anonymous failed session setup with %s\n",
01668 nt_errstr(nt_status)));
01669 cli_shutdown(cli);
01670 return nt_status;
01671 }
01672 }
01673
01674 if (service) {
01675 if (!cli_send_tconX(cli, service, service_type, password, pw_len)) {
01676 nt_status = cli_nt_error(cli);
01677 DEBUG(1,("failed tcon_X with %s\n", nt_errstr(nt_status)));
01678 cli_shutdown(cli);
01679 if (NT_STATUS_IS_OK(nt_status)) {
01680 nt_status = NT_STATUS_UNSUCCESSFUL;
01681 }
01682 return nt_status;
01683 }
01684 }
01685
01686 cli_init_creds(cli, user, domain, password);
01687
01688 *output_cli = cli;
01689 return NT_STATUS_OK;
01690 }
01691
01692
01693
01694
01695
01696 BOOL attempt_netbios_session_request(struct cli_state **ppcli, const char *srchost, const char *desthost,
01697 struct in_addr *pdest_ip)
01698 {
01699 struct nmb_name calling, called;
01700
01701 make_nmb_name(&calling, srchost, 0x0);
01702
01703
01704
01705
01706
01707
01708 if(is_ipaddress(desthost)) {
01709 make_nmb_name(&called, star_smbserver_name, 0x20);
01710 } else {
01711 make_nmb_name(&called, desthost, 0x20);
01712 }
01713
01714 if (!cli_session_request(*ppcli, &calling, &called)) {
01715 NTSTATUS status;
01716 struct nmb_name smbservername;
01717
01718 make_nmb_name(&smbservername, star_smbserver_name, 0x20);
01719
01720
01721
01722
01723
01724
01725 if (nmb_name_equal(&called, &smbservername)) {
01726
01727
01728
01729
01730
01731 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
01732 with error %s.\n", desthost, cli_errstr(*ppcli) ));
01733 return False;
01734 }
01735
01736
01737 cli_shutdown(*ppcli);
01738
01739 *ppcli = cli_initialise();
01740 if (!*ppcli) {
01741
01742 return False;
01743 }
01744
01745 status = cli_connect(*ppcli, desthost, pdest_ip);
01746 if (!NT_STATUS_IS_OK(status) ||
01747 !cli_session_request(*ppcli, &calling, &smbservername)) {
01748 DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
01749 name *SMBSERVER with error %s\n", desthost, cli_errstr(*ppcli) ));
01750 return False;
01751 }
01752 }
01753
01754 return True;
01755 }
01756
01757
01758
01759
01760
01761
01762
01763
01764 NTSTATUS cli_raw_tcon(struct cli_state *cli,
01765 const char *service, const char *pass, const char *dev,
01766 uint16 *max_xmit, uint16 *tid)
01767 {
01768 char *p;
01769
01770 if (!lp_client_plaintext_auth() && (*pass)) {
01771 DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'"
01772 " is disabled\n"));
01773 return NT_STATUS_ACCESS_DENIED;
01774 }
01775
01776 memset(cli->outbuf,'\0',smb_size);
01777 memset(cli->inbuf,'\0',smb_size);
01778
01779 set_message(cli->outbuf, 0, 0, True);
01780 SCVAL(cli->outbuf,smb_com,SMBtcon);
01781 cli_setup_packet(cli);
01782
01783 p = smb_buf(cli->outbuf);
01784 *p++ = 4; p += clistr_push(cli, p, service, -1, STR_TERMINATE | STR_NOALIGN);
01785 *p++ = 4; p += clistr_push(cli, p, pass, -1, STR_TERMINATE | STR_NOALIGN);
01786 *p++ = 4; p += clistr_push(cli, p, dev, -1, STR_TERMINATE | STR_NOALIGN);
01787
01788 cli_setup_bcc(cli, p);
01789
01790 cli_send_smb(cli);
01791 if (!cli_receive_smb(cli)) {
01792 return NT_STATUS_UNEXPECTED_NETWORK_ERROR;
01793 }
01794
01795 if (cli_is_error(cli)) {
01796 return cli_nt_error(cli);
01797 }
01798
01799 *max_xmit = SVAL(cli->inbuf, smb_vwv0);
01800 *tid = SVAL(cli->inbuf, smb_vwv1);
01801
01802 return NT_STATUS_OK;
01803 }
01804
01805
01806
01807 struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip,
01808 struct user_auth_info *user_info)
01809 {
01810 struct cli_state *cli;
01811 pstring myname;
01812 NTSTATUS nt_status;
01813
01814 get_myname(myname);
01815
01816 nt_status = cli_full_connection(&cli, myname, server, server_ip, 0, "IPC$", "IPC",
01817 user_info->username, lp_workgroup(), user_info->password,
01818 CLI_FULL_CONNECTION_ANONYMOUS_FALLBACK, Undefined, NULL);
01819
01820 if (NT_STATUS_IS_OK(nt_status)) {
01821 return cli;
01822 } else if (is_ipaddress(server)) {
01823
01824 fstring remote_name;
01825
01826 if (name_status_find("*", 0, 0, *server_ip, remote_name)) {
01827 cli = get_ipc_connect(remote_name, server_ip, user_info);
01828 if (cli)
01829 return cli;
01830 }
01831 }
01832 return NULL;
01833 }
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847 struct cli_state *get_ipc_connect_master_ip(struct ip_service * mb_ip, pstring workgroup, struct user_auth_info *user_info)
01848 {
01849 static fstring name;
01850 struct cli_state *cli;
01851 struct in_addr server_ip;
01852
01853 DEBUG(99, ("Looking up name of master browser %s\n",
01854 inet_ntoa(mb_ip->ip)));
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867 if (!name_status_find("*", 0, 0x1d, mb_ip->ip, name) &&
01868 !name_status_find(MSBROWSE, 1, 0x1d, mb_ip->ip, name)) {
01869
01870 DEBUG(99, ("Could not retrieve name status for %s\n",
01871 inet_ntoa(mb_ip->ip)));
01872 return NULL;
01873 }
01874
01875 if (!find_master_ip(name, &server_ip)) {
01876 DEBUG(99, ("Could not find master ip for %s\n", name));
01877 return NULL;
01878 }
01879
01880 pstrcpy(workgroup, name);
01881
01882 DEBUG(4, ("found master browser %s, %s\n",
01883 name, inet_ntoa(mb_ip->ip)));
01884
01885 cli = get_ipc_connect(inet_ntoa(server_ip), &server_ip, user_info);
01886
01887 return cli;
01888
01889 }
01890
01891
01892
01893
01894
01895
01896 struct cli_state *get_ipc_connect_master_ip_bcast(pstring workgroup, struct user_auth_info *user_info)
01897 {
01898 struct ip_service *ip_list;
01899 struct cli_state *cli;
01900 int i, count;
01901
01902 DEBUG(99, ("Do broadcast lookup for workgroups on local network\n"));
01903
01904
01905
01906 if (!name_resolve_bcast(MSBROWSE, 1, &ip_list, &count)) {
01907 DEBUG(99, ("No master browsers responded\n"));
01908 return False;
01909 }
01910
01911 for (i = 0; i < count; i++) {
01912 DEBUG(99, ("Found master browser %s\n", inet_ntoa(ip_list[i].ip)));
01913
01914 cli = get_ipc_connect_master_ip(&ip_list[i], workgroup, user_info);
01915 if (cli)
01916 return(cli);
01917 }
01918
01919 return NULL;
01920 }