データ構造 | |
struct | ads_service_principal |
関数 | |
static ADS_STATUS | ads_sasl_spnego_ntlmssp_bind (ADS_STRUCT *ads) |
static void | ads_free_service_principal (struct ads_service_principal *p) |
static ADS_STATUS | ads_generate_service_principal (ADS_STRUCT *ads, const char *given_principal, struct ads_service_principal *p) |
static ADS_STATUS | ads_sasl_spnego_rawkrb5_bind (ADS_STRUCT *ads, const char *principal) |
static ADS_STATUS | ads_sasl_spnego_krb5_bind (ADS_STRUCT *ads, struct ads_service_principal *p) |
static ADS_STATUS | ads_sasl_spnego_bind (ADS_STRUCT *ads) |
static ADS_STATUS | ads_sasl_gssapi_bind (ADS_STRUCT *ads) |
ADS_STATUS | ads_sasl_bind (ADS_STRUCT *ads) |
変数 | |
struct { | |
const char * name | |
ADS_STATUS(* fn )(ADS_STRUCT *) | |
} | sasl_mechanisms [] |
static ADS_STATUS ads_sasl_spnego_ntlmssp_bind | ( | ADS_STRUCT * | ads | ) | [static] |
参照先 ADS_STRUCT::auth・data_blob_::data・data_blob()・data_blob_free()・gen_negTokenInit()・ADS_STRUCT::ld・LDAP_SASL_BIND_IN_PROGRESS・data_blob_::length・ntlmssp_state::neg_flags・ntlmssp_client_start()・ntlmssp_end()・ntlmssp_set_domain()・ntlmssp_set_password()・ntlmssp_set_username()・ntlmssp_update()・ADS_STRUCT::password・ADS_STRUCT::realm・spnego_gen_auth()・spnego_parse_auth_response()・spnego_parse_challenge()・ADS_STRUCT::user_name.
00030 { 00031 DATA_BLOB msg1 = data_blob(NULL, 0); 00032 DATA_BLOB blob = data_blob(NULL, 0); 00033 DATA_BLOB blob_in = data_blob(NULL, 0); 00034 DATA_BLOB blob_out = data_blob(NULL, 0); 00035 struct berval cred, *scred = NULL; 00036 int rc; 00037 NTSTATUS nt_status; 00038 int turn = 1; 00039 00040 struct ntlmssp_state *ntlmssp_state; 00041 00042 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_client_start(&ntlmssp_state))) { 00043 return ADS_ERROR_NT(nt_status); 00044 } 00045 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN; 00046 00047 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, ads->auth.user_name))) { 00048 return ADS_ERROR_NT(nt_status); 00049 } 00050 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, ads->auth.realm))) { 00051 return ADS_ERROR_NT(nt_status); 00052 } 00053 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, ads->auth.password))) { 00054 return ADS_ERROR_NT(nt_status); 00055 } 00056 00057 blob_in = data_blob(NULL, 0); 00058 00059 do { 00060 nt_status = ntlmssp_update(ntlmssp_state, 00061 blob_in, &blob_out); 00062 data_blob_free(&blob_in); 00063 if ((NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) 00064 || NT_STATUS_IS_OK(nt_status)) 00065 && blob_out.length) { 00066 if (turn == 1) { 00067 /* and wrap it in a SPNEGO wrapper */ 00068 msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out); 00069 } else { 00070 /* wrap it in SPNEGO */ 00071 msg1 = spnego_gen_auth(blob_out); 00072 } 00073 00074 data_blob_free(&blob_out); 00075 00076 cred.bv_val = (char *)msg1.data; 00077 cred.bv_len = msg1.length; 00078 scred = NULL; 00079 rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred); 00080 data_blob_free(&msg1); 00081 if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) { 00082 if (scred) { 00083 ber_bvfree(scred); 00084 } 00085 00086 ntlmssp_end(&ntlmssp_state); 00087 return ADS_ERROR(rc); 00088 } 00089 if (scred) { 00090 blob = data_blob(scred->bv_val, scred->bv_len); 00091 ber_bvfree(scred); 00092 } else { 00093 blob = data_blob(NULL, 0); 00094 } 00095 00096 } else { 00097 00098 ntlmssp_end(&ntlmssp_state); 00099 data_blob_free(&blob_out); 00100 return ADS_ERROR_NT(nt_status); 00101 } 00102 00103 if ((turn == 1) && 00104 (rc == LDAP_SASL_BIND_IN_PROGRESS)) { 00105 DATA_BLOB tmp_blob = data_blob(NULL, 0); 00106 /* the server might give us back two challenges */ 00107 if (!spnego_parse_challenge(blob, &blob_in, 00108 &tmp_blob)) { 00109 00110 ntlmssp_end(&ntlmssp_state); 00111 data_blob_free(&blob); 00112 DEBUG(3,("Failed to parse challenges\n")); 00113 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); 00114 } 00115 data_blob_free(&tmp_blob); 00116 } else if (rc == LDAP_SASL_BIND_IN_PROGRESS) { 00117 if (!spnego_parse_auth_response(blob, nt_status, 00118 &blob_in)) { 00119 00120 ntlmssp_end(&ntlmssp_state); 00121 data_blob_free(&blob); 00122 DEBUG(3,("Failed to parse auth response\n")); 00123 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); 00124 } 00125 } 00126 data_blob_free(&blob); 00127 data_blob_free(&blob_out); 00128 turn++; 00129 } while (rc == LDAP_SASL_BIND_IN_PROGRESS && !NT_STATUS_IS_OK(nt_status)); 00130 00131 /* we have a reference conter on ntlmssp_state, if we are signing 00132 then the state will be kept by the signing engine */ 00133 00134 ntlmssp_end(&ntlmssp_state); 00135 00136 return ADS_ERROR(rc); 00137 }
static void ads_free_service_principal | ( | struct ads_service_principal * | p | ) | [static] |
参照先 ads_service_principal::name・ads_service_principal::string.
参照元 ads_generate_service_principal()・ads_sasl_spnego_bind().
00148 { 00149 SAFE_FREE(p->string); 00150 00151 #ifdef HAVE_GSSAPI 00152 if (p->name) { 00153 uint32 minor_status; 00154 gss_release_name(&minor_status, &p->name); 00155 } 00156 #endif 00157 ZERO_STRUCTP(p); 00158 }
static ADS_STATUS ads_generate_service_principal | ( | ADS_STRUCT * | ads, | |
const char * | given_principal, | |||
struct ads_service_principal * | p | |||
) | [static] |
参照先 ads_free_service_principal()・ads_guess_service_principal()・ads_service_principal::name・status・strequal()・ads_service_principal::string.
00163 { 00164 ADS_STATUS status; 00165 #ifdef HAVE_GSSAPI 00166 gss_buffer_desc input_name; 00167 /* GSS_KRB5_NT_PRINCIPAL_NAME */ 00168 gss_OID_desc nt_principal = 00169 {10, CONST_DISCARD(char *, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01")}; 00170 uint32 minor_status; 00171 int gss_rc; 00172 #endif 00173 00174 ZERO_STRUCTP(p); 00175 00176 /* I've seen a child Windows 2000 domain not send 00177 the principal name back in the first round of 00178 the SASL bind reply. So we guess based on server 00179 name and realm. --jerry */ 00180 /* Also try best guess when we get the w2k8 ignore 00181 principal back - gd */ 00182 00183 if (!given_principal || 00184 strequal(given_principal, ADS_IGNORE_PRINCIPAL)) { 00185 00186 status = ads_guess_service_principal(ads, &p->string); 00187 if (!ADS_ERR_OK(status)) { 00188 return status; 00189 } 00190 } else { 00191 p->string = SMB_STRDUP(given_principal); 00192 if (!p->string) { 00193 return ADS_ERROR(LDAP_NO_MEMORY); 00194 } 00195 } 00196 00197 #ifdef HAVE_GSSAPI 00198 input_name.value = p->string; 00199 input_name.length = strlen(p->string); 00200 00201 gss_rc = gss_import_name(&minor_status, &input_name, &nt_principal, &p->name); 00202 if (gss_rc) { 00203 ads_free_service_principal(p); 00204 return ADS_ERROR_GSS(gss_rc, minor_status); 00205 } 00206 #endif 00207 00208 return ADS_SUCCESS; 00209 }
static ADS_STATUS ads_sasl_spnego_rawkrb5_bind | ( | ADS_STRUCT * | ads, | |
const char * | principal | |||
) | [static] |
参照先 ADS_STRUCT::auth・data_blob_::data・data_blob()・data_blob_free()・ADS_STRUCT::ld・data_blob_::length・spnego_gen_negTokenTarg()・ADS_STRUCT::tgs_expire・ADS_STRUCT::time_offset.
参照元 ads_sasl_spnego_krb5_bind().
00215 { 00216 DATA_BLOB blob = data_blob(NULL, 0); 00217 struct berval cred, *scred = NULL; 00218 DATA_BLOB session_key = data_blob(NULL, 0); 00219 int rc; 00220 00221 rc = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, &blob, &session_key, 0, 00222 &ads->auth.tgs_expire); 00223 00224 if (rc) { 00225 return ADS_ERROR_KRB5(rc); 00226 } 00227 00228 /* now send the auth packet and we should be done */ 00229 cred.bv_val = (char *)blob.data; 00230 cred.bv_len = blob.length; 00231 00232 rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred); 00233 00234 data_blob_free(&blob); 00235 data_blob_free(&session_key); 00236 if(scred) 00237 ber_bvfree(scred); 00238 00239 return ADS_ERROR(rc); 00240 }
static ADS_STATUS ads_sasl_spnego_krb5_bind | ( | ADS_STRUCT * | ads, | |
struct ads_service_principal * | p | |||
) | [static] |
参照先 ads_sasl_spnego_rawkrb5_bind()・ads_service_principal::string.
00244 { 00245 return ads_sasl_spnego_rawkrb5_bind(ads, p->string); 00246 }
static ADS_STATUS ads_sasl_spnego_bind | ( | ADS_STRUCT * | ads | ) | [static] |
参照先 ads_errstr()・ads_free_service_principal()・ads_generate_service_principal()・ads_kinit_password()・ads_sasl_spnego_krb5_bind()・ads_sasl_spnego_ntlmssp_bind()・ADS_STRUCT::auth・data_blob_::data・data_blob()・data_blob_free()・failed・file_save()・ADS_STRUCT::flags・ADS_STRUCT::ld・LDAP_SASL_BIND_IN_PROGRESS・data_blob_::length・spnego_parse_negTokenInit()・status.
00254 { 00255 struct berval *scred=NULL; 00256 int rc, i; 00257 ADS_STATUS status; 00258 DATA_BLOB blob; 00259 char *given_principal = NULL; 00260 char *OIDs[ASN1_MAX_OIDS]; 00261 #ifdef HAVE_KRB5 00262 BOOL got_kerberos_mechanism = False; 00263 #endif 00264 00265 rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", NULL, NULL, NULL, &scred); 00266 00267 if (rc != LDAP_SASL_BIND_IN_PROGRESS) { 00268 status = ADS_ERROR(rc); 00269 goto failed; 00270 } 00271 00272 blob = data_blob(scred->bv_val, scred->bv_len); 00273 00274 ber_bvfree(scred); 00275 00276 #if 0 00277 file_save("sasl_spnego.dat", blob.data, blob.length); 00278 #endif 00279 00280 /* the server sent us the first part of the SPNEGO exchange in the negprot 00281 reply */ 00282 if (!spnego_parse_negTokenInit(blob, OIDs, &given_principal)) { 00283 data_blob_free(&blob); 00284 status = ADS_ERROR(LDAP_OPERATIONS_ERROR); 00285 goto failed; 00286 } 00287 data_blob_free(&blob); 00288 00289 /* make sure the server understands kerberos */ 00290 for (i=0;OIDs[i];i++) { 00291 DEBUG(3,("ads_sasl_spnego_bind: got OID=%s\n", OIDs[i])); 00292 #ifdef HAVE_KRB5 00293 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 || 00294 strcmp(OIDs[i], OID_KERBEROS5) == 0) { 00295 got_kerberos_mechanism = True; 00296 } 00297 #endif 00298 free(OIDs[i]); 00299 } 00300 DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", given_principal)); 00301 00302 #ifdef HAVE_KRB5 00303 if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) && 00304 got_kerberos_mechanism) 00305 { 00306 struct ads_service_principal p; 00307 00308 status = ads_generate_service_principal(ads, given_principal, &p); 00309 SAFE_FREE(given_principal); 00310 if (!ADS_ERR_OK(status)) { 00311 return status; 00312 } 00313 00314 status = ads_sasl_spnego_krb5_bind(ads, &p); 00315 if (ADS_ERR_OK(status)) { 00316 ads_free_service_principal(&p); 00317 return status; 00318 } 00319 00320 DEBUG(10,("ads_sasl_spnego_krb5_bind failed with: %s, " 00321 "calling kinit\n", ads_errstr(status))); 00322 00323 status = ADS_ERROR_KRB5(ads_kinit_password(ads)); 00324 00325 if (ADS_ERR_OK(status)) { 00326 status = ads_sasl_spnego_krb5_bind(ads, &p); 00327 if (!ADS_ERR_OK(status)) { 00328 DEBUG(0,("kinit succeeded but " 00329 "ads_sasl_spnego_krb5_bind failed: %s\n", 00330 ads_errstr(status))); 00331 } 00332 } 00333 00334 ads_free_service_principal(&p); 00335 00336 /* only fallback to NTLMSSP if allowed */ 00337 if (ADS_ERR_OK(status) || 00338 !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) { 00339 return status; 00340 } 00341 } else 00342 #endif 00343 { 00344 SAFE_FREE(given_principal); 00345 } 00346 00347 /* lets do NTLMSSP ... this has the big advantage that we don't need 00348 to sync clocks, and we don't rely on special versions of the krb5 00349 library for HMAC_MD4 encryption */ 00350 return ads_sasl_spnego_ntlmssp_bind(ads); 00351 00352 failed: 00353 return status; 00354 }
static ADS_STATUS ads_sasl_gssapi_bind | ( | ADS_STRUCT * | ads | ) | [static] |
参照先 asprintf()・ADS_STRUCT::config・ctx・failed・krb5_set_default_tgs_ktypes()・ADS_STRUCT::ld・LDAP_SASL_BIND_IN_PROGRESS・ADS_STRUCT::ldap_server_name・ADS_STRUCT::realm・smb_krb5_parse_name()・status.
00366 { 00367 uint32 minor_status; 00368 gss_name_t serv_name; 00369 gss_buffer_desc input_name; 00370 gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT; 00371 gss_OID mech_type = GSS_C_NULL_OID; 00372 gss_buffer_desc output_token, input_token; 00373 uint32 ret_flags, conf_state; 00374 struct berval cred; 00375 struct berval *scred = NULL; 00376 int i=0; 00377 int gss_rc, rc; 00378 uint8 *p; 00379 uint32 max_msg_size = 0; 00380 char *sname = NULL; 00381 ADS_STATUS status; 00382 krb5_principal principal = NULL; 00383 krb5_context ctx = NULL; 00384 krb5_enctype enc_types[] = { 00385 #ifdef ENCTYPE_ARCFOUR_HMAC 00386 ENCTYPE_ARCFOUR_HMAC, 00387 #endif 00388 ENCTYPE_DES_CBC_MD5, 00389 ENCTYPE_NULL}; 00390 gss_OID_desc nt_principal = 00391 {10, CONST_DISCARD(char *, "\052\206\110\206\367\022\001\002\002\002")}; 00392 00393 /* we need to fetch a service ticket as the ldap user in the 00394 servers realm, regardless of our realm */ 00395 asprintf(&sname, "ldap/%s@%s", ads->config.ldap_server_name, ads->config.realm); 00396 00397 initialize_krb5_error_table(); 00398 status = ADS_ERROR_KRB5(krb5_init_context(&ctx)); 00399 if (!ADS_ERR_OK(status)) { 00400 SAFE_FREE(sname); 00401 return status; 00402 } 00403 status = ADS_ERROR_KRB5(krb5_set_default_tgs_ktypes(ctx, enc_types)); 00404 if (!ADS_ERR_OK(status)) { 00405 SAFE_FREE(sname); 00406 krb5_free_context(ctx); 00407 return status; 00408 } 00409 status = ADS_ERROR_KRB5(smb_krb5_parse_name(ctx, sname, &principal)); 00410 if (!ADS_ERR_OK(status)) { 00411 SAFE_FREE(sname); 00412 krb5_free_context(ctx); 00413 return status; 00414 } 00415 00416 input_name.value = &principal; 00417 input_name.length = sizeof(principal); 00418 00419 gss_rc = gss_import_name(&minor_status, &input_name, &nt_principal, &serv_name); 00420 00421 /* 00422 * The MIT libraries have a *HORRIBLE* bug - input_value.value needs 00423 * to point to the *address* of the krb5_principal, and the gss libraries 00424 * to a shallow copy of the krb5_principal pointer - so we need to keep 00425 * the krb5_principal around until we do the gss_release_name. MIT *SUCKS* ! 00426 * Just one more way in which MIT engineers screwed me over.... JRA. 00427 */ 00428 00429 SAFE_FREE(sname); 00430 00431 if (gss_rc) { 00432 krb5_free_principal(ctx, principal); 00433 krb5_free_context(ctx); 00434 return ADS_ERROR_GSS(gss_rc, minor_status); 00435 } 00436 00437 input_token.value = NULL; 00438 input_token.length = 0; 00439 00440 for (i=0; i < MAX_GSS_PASSES; i++) { 00441 gss_rc = gss_init_sec_context(&minor_status, 00442 GSS_C_NO_CREDENTIAL, 00443 &context_handle, 00444 serv_name, 00445 mech_type, 00446 GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG, 00447 0, 00448 NULL, 00449 &input_token, 00450 NULL, 00451 &output_token, 00452 &ret_flags, 00453 NULL); 00454 00455 if (input_token.value) { 00456 gss_release_buffer(&minor_status, &input_token); 00457 } 00458 00459 if (gss_rc && gss_rc != GSS_S_CONTINUE_NEEDED) { 00460 status = ADS_ERROR_GSS(gss_rc, minor_status); 00461 goto failed; 00462 } 00463 00464 cred.bv_val = (char *)output_token.value; 00465 cred.bv_len = output_token.length; 00466 00467 rc = ldap_sasl_bind_s(ads->ld, NULL, "GSSAPI", &cred, NULL, NULL, 00468 &scred); 00469 if (rc != LDAP_SASL_BIND_IN_PROGRESS) { 00470 status = ADS_ERROR(rc); 00471 goto failed; 00472 } 00473 00474 if (output_token.value) { 00475 gss_release_buffer(&minor_status, &output_token); 00476 } 00477 00478 if (scred) { 00479 input_token.value = scred->bv_val; 00480 input_token.length = scred->bv_len; 00481 } else { 00482 input_token.value = NULL; 00483 input_token.length = 0; 00484 } 00485 00486 if (gss_rc == 0) break; 00487 } 00488 00489 gss_rc = gss_unwrap(&minor_status,context_handle,&input_token,&output_token, 00490 (int *)&conf_state,NULL); 00491 if (gss_rc) { 00492 status = ADS_ERROR_GSS(gss_rc, minor_status); 00493 goto failed; 00494 } 00495 00496 gss_release_buffer(&minor_status, &input_token); 00497 00498 p = (uint8 *)output_token.value; 00499 00500 #if 0 00501 file_save("sasl_gssapi.dat", output_token.value, output_token.length); 00502 #endif 00503 00504 if (p) { 00505 max_msg_size = (p[1]<<16) | (p[2]<<8) | p[3]; 00506 } 00507 00508 gss_release_buffer(&minor_status, &output_token); 00509 00510 output_token.value = SMB_MALLOC(strlen(ads->config.bind_path) + 8); 00511 p = (uint8 *)output_token.value; 00512 00513 *p++ = 1; /* no sign & seal selection */ 00514 /* choose the same size as the server gave us */ 00515 *p++ = max_msg_size>>16; 00516 *p++ = max_msg_size>>8; 00517 *p++ = max_msg_size; 00518 snprintf((char *)p, strlen(ads->config.bind_path)+4, "dn:%s", ads->config.bind_path); 00519 p += strlen((const char *)p); 00520 00521 output_token.length = PTR_DIFF(p, output_token.value); 00522 00523 gss_rc = gss_wrap(&minor_status, context_handle,0,GSS_C_QOP_DEFAULT, 00524 &output_token, (int *)&conf_state, 00525 &input_token); 00526 if (gss_rc) { 00527 status = ADS_ERROR_GSS(gss_rc, minor_status); 00528 goto failed; 00529 } 00530 00531 free(output_token.value); 00532 00533 cred.bv_val = (char *)input_token.value; 00534 cred.bv_len = input_token.length; 00535 00536 rc = ldap_sasl_bind_s(ads->ld, NULL, "GSSAPI", &cred, NULL, NULL, 00537 &scred); 00538 status = ADS_ERROR(rc); 00539 00540 gss_release_buffer(&minor_status, &input_token); 00541 00542 failed: 00543 00544 gss_release_name(&minor_status, &serv_name); 00545 if (context_handle != GSS_C_NO_CONTEXT) 00546 gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER); 00547 krb5_free_principal(ctx, principal); 00548 krb5_free_context(ctx); 00549 00550 if(scred) 00551 ber_bvfree(scred); 00552 return status; 00553 }
ADS_STATUS ads_sasl_bind | ( | ADS_STRUCT * | ads | ) |
参照先 ads_do_search()・ADS_STRUCT::ld・name・sasl_mechanisms・status・values.
参照元 ads_connect().
00569 { 00570 const char *attrs[] = {"supportedSASLMechanisms", NULL}; 00571 char **values; 00572 ADS_STATUS status; 00573 int i, j; 00574 LDAPMessage *res; 00575 00576 /* get a list of supported SASL mechanisms */ 00577 status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res); 00578 if (!ADS_ERR_OK(status)) return status; 00579 00580 values = ldap_get_values(ads->ld, res, "supportedSASLMechanisms"); 00581 00582 /* try our supported mechanisms in order */ 00583 for (i=0;sasl_mechanisms[i].name;i++) { 00584 /* see if the server supports it */ 00585 for (j=0;values && values[j];j++) { 00586 if (strcmp(values[j], sasl_mechanisms[i].name) == 0) { 00587 DEBUG(4,("Found SASL mechanism %s\n", values[j])); 00588 status = sasl_mechanisms[i].fn(ads); 00589 ldap_value_free(values); 00590 ldap_msgfree(res); 00591 return status; 00592 } 00593 } 00594 } 00595 00596 ldap_value_free(values); 00597 ldap_msgfree(res); 00598 return ADS_ERROR(LDAP_AUTH_METHOD_NOT_SUPPORTED); 00599 }
ADS_STATUS(* fn)(ADS_STRUCT *) |
struct { ... } sasl_mechanisms[] [static] |
参照元 ads_sasl_bind().