Changeset 988 for vendor/current/source3/libads/sasl.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/libads/sasl.c
r919 r988 20 20 #include "includes.h" 21 21 #include "../libcli/auth/spnego.h" 22 #include "../libcli/auth/ntlmssp.h" 22 #include "auth/credentials/credentials.h" 23 #include "auth/gensec/gensec.h" 24 #include "auth_generic.h" 23 25 #include "ads.h" 24 26 #include "smb_krb5.h" 27 #include "system/gssapi.h" 28 #include "lib/param/loadparm.h" 25 29 26 30 #ifdef HAVE_LDAP 27 31 28 static ADS_STATUS ads_sasl_ ntlmssp_wrap(ADS_STRUCT *ads, uint8 *buf, uint32len)29 { 30 struct ntlmssp_state *ntlmssp_state=31 (struct ntlmssp_state *)ads->ldap.wrap_private_data;32 ADS_STATUS status;32 static ADS_STATUS ads_sasl_gensec_wrap(ADS_STRUCT *ads, uint8_t *buf, uint32_t len) 33 { 34 struct gensec_security *gensec_security = 35 talloc_get_type_abort(ads->ldap.wrap_private_data, 36 struct gensec_security); 33 37 NTSTATUS nt_status; 34 DATA_BLOB sig; 35 TALLOC_CTX *frame; 36 uint8 *dptr = ads->ldap.out.buf + (4 + NTLMSSP_SIG_SIZE); 37 38 frame = talloc_stackframe(); 39 /* copy the data to the right location */ 40 memcpy(dptr, buf, len); 41 42 /* create the signature and may encrypt the data */ 43 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) { 44 nt_status = ntlmssp_seal_packet(ntlmssp_state, 45 frame, 46 dptr, len, 47 dptr, len, 48 &sig); 49 } else { 50 nt_status = ntlmssp_sign_packet(ntlmssp_state, 51 frame, 52 dptr, len, 53 dptr, len, 54 &sig); 55 } 56 status = ADS_ERROR_NT(nt_status); 57 if (!ADS_ERR_OK(status)) return status; 58 59 /* copy the signature to the right location */ 60 memcpy(ads->ldap.out.buf + 4, 61 sig.data, NTLMSSP_SIG_SIZE); 38 DATA_BLOB unwrapped, wrapped; 39 TALLOC_CTX *frame = talloc_stackframe(); 40 41 unwrapped = data_blob_const(buf, len); 42 43 nt_status = gensec_wrap(gensec_security, frame, &unwrapped, &wrapped); 44 if (!NT_STATUS_IS_OK(nt_status)) { 45 TALLOC_FREE(frame); 46 return ADS_ERROR_NT(nt_status); 47 } 48 49 if ((ads->ldap.out.size - 4) < wrapped.length) { 50 TALLOC_FREE(frame); 51 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR); 52 } 53 54 /* copy the wrapped blob to the right location */ 55 memcpy(ads->ldap.out.buf + 4, wrapped.data, wrapped.length); 56 57 /* set how many bytes must be written to the underlying socket */ 58 ads->ldap.out.left = 4 + wrapped.length; 62 59 63 60 TALLOC_FREE(frame); 64 61 62 return ADS_SUCCESS; 63 } 64 65 static ADS_STATUS ads_sasl_gensec_unwrap(ADS_STRUCT *ads) 66 { 67 struct gensec_security *gensec_security = 68 talloc_get_type_abort(ads->ldap.wrap_private_data, 69 struct gensec_security); 70 NTSTATUS nt_status; 71 DATA_BLOB unwrapped, wrapped; 72 TALLOC_CTX *frame = talloc_stackframe(); 73 74 wrapped = data_blob_const(ads->ldap.in.buf + 4, ads->ldap.in.ofs - 4); 75 76 nt_status = gensec_unwrap(gensec_security, frame, &wrapped, &unwrapped); 77 if (!NT_STATUS_IS_OK(nt_status)) { 78 TALLOC_FREE(frame); 79 return ADS_ERROR_NT(nt_status); 80 } 81 82 if (wrapped.length < unwrapped.length) { 83 TALLOC_FREE(frame); 84 return ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR); 85 } 86 87 /* copy the wrapped blob to the right location */ 88 memcpy(ads->ldap.in.buf + 4, unwrapped.data, unwrapped.length); 89 65 90 /* set how many bytes must be written to the underlying socket */ 66 ads->ldap.out.left = 4 + NTLMSSP_SIG_SIZE + len; 91 ads->ldap.in.left = unwrapped.length; 92 ads->ldap.in.ofs = 4; 93 94 TALLOC_FREE(frame); 67 95 68 96 return ADS_SUCCESS; 69 97 } 70 98 71 static ADS_STATUS ads_sasl_ntlmssp_unwrap(ADS_STRUCT *ads) 72 { 73 struct ntlmssp_state *ntlmssp_state = 74 (struct ntlmssp_state *)ads->ldap.wrap_private_data; 75 ADS_STATUS status; 76 NTSTATUS nt_status; 77 DATA_BLOB sig; 78 uint8 *dptr = ads->ldap.in.buf + (4 + NTLMSSP_SIG_SIZE); 79 uint32 dlen = ads->ldap.in.ofs - (4 + NTLMSSP_SIG_SIZE); 80 81 /* wrap the signature into a DATA_BLOB */ 82 sig = data_blob_const(ads->ldap.in.buf + 4, NTLMSSP_SIG_SIZE); 83 84 /* verify the signature and maybe decrypt the data */ 85 if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) { 86 nt_status = ntlmssp_unseal_packet(ntlmssp_state, 87 dptr, dlen, 88 dptr, dlen, 89 &sig); 90 } else { 91 nt_status = ntlmssp_check_packet(ntlmssp_state, 92 dptr, dlen, 93 dptr, dlen, 94 &sig); 95 } 96 status = ADS_ERROR_NT(nt_status); 97 if (!ADS_ERR_OK(status)) return status; 98 99 /* set the amount of bytes for the upper layer and set the ofs to the data */ 100 ads->ldap.in.left = dlen; 101 ads->ldap.in.ofs = 4 + NTLMSSP_SIG_SIZE; 102 103 return ADS_SUCCESS; 104 } 105 106 static void ads_sasl_ntlmssp_disconnect(ADS_STRUCT *ads) 107 { 108 struct ntlmssp_state *ntlmssp_state = 109 (struct ntlmssp_state *)ads->ldap.wrap_private_data; 110 111 TALLOC_FREE(ntlmssp_state); 99 static void ads_sasl_gensec_disconnect(ADS_STRUCT *ads) 100 { 101 struct gensec_security *gensec_security = 102 talloc_get_type_abort(ads->ldap.wrap_private_data, 103 struct gensec_security); 104 105 TALLOC_FREE(gensec_security); 112 106 113 107 ads->ldap.wrap_ops = NULL; … … 115 109 } 116 110 117 static const struct ads_saslwrap_ops ads_sasl_ ntlmssp_ops = {118 .name = " ntlmssp",119 .wrap = ads_sasl_ ntlmssp_wrap,120 .unwrap = ads_sasl_ ntlmssp_unwrap,121 .disconnect = ads_sasl_ ntlmssp_disconnect111 static const struct ads_saslwrap_ops ads_sasl_gensec_ops = { 112 .name = "gensec", 113 .wrap = ads_sasl_gensec_wrap, 114 .unwrap = ads_sasl_gensec_unwrap, 115 .disconnect = ads_sasl_gensec_disconnect 122 116 }; 123 117 124 118 /* 125 perform a LDAP/SASL/SPNEGO/ NTLMSSPbind (just how many layers can119 perform a LDAP/SASL/SPNEGO/{NTLMSSP,KRB5} bind (just how many layers can 126 120 we fit on one socket??) 127 121 */ 128 static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads) 129 { 130 DATA_BLOB msg1 = data_blob_null; 131 DATA_BLOB blob = data_blob_null; 122 static ADS_STATUS ads_sasl_spnego_gensec_bind(ADS_STRUCT *ads, 123 const char *sasl, 124 enum credentials_use_kerberos krb5_state, 125 const char *target_service, 126 const char *target_hostname, 127 const DATA_BLOB server_blob) 128 { 132 129 DATA_BLOB blob_in = data_blob_null; 133 130 DATA_BLOB blob_out = data_blob_null; 134 struct berval cred, *scred = NULL;135 131 int rc; 136 132 NTSTATUS nt_status; 137 133 ADS_STATUS status; 138 int turn = 1; 139 uint32 features = 0; 140 141 struct ntlmssp_state *ntlmssp_state; 142 143 nt_status = ntlmssp_client_start(NULL, 144 global_myname(), 145 lp_workgroup(), 146 lp_client_ntlmv2_auth(), 147 &ntlmssp_state); 134 struct auth_generic_state *auth_generic_state; 135 bool use_spnego_principal = lp_client_use_spnego_principal(); 136 const char *sasl_list[] = { sasl, NULL }; 137 NTTIME end_nt_time; 138 139 nt_status = auth_generic_client_prepare(NULL, &auth_generic_state); 148 140 if (!NT_STATUS_IS_OK(nt_status)) { 149 141 return ADS_ERROR_NT(nt_status); 150 142 } 151 ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_SIGN; 152 153 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, ads->auth.user_name))) { 143 144 if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_username(auth_generic_state, ads->auth.user_name))) { 154 145 return ADS_ERROR_NT(nt_status); 155 146 } 156 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, ads->auth.realm))) {147 if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_domain(auth_generic_state, ads->auth.realm))) { 157 148 return ADS_ERROR_NT(nt_status); 158 149 } 159 if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, ads->auth.password))) {150 if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_password(auth_generic_state, ads->auth.password))) { 160 151 return ADS_ERROR_NT(nt_status); 152 } 153 154 if (server_blob.length == 0) { 155 use_spnego_principal = false; 156 } 157 158 if (krb5_state == CRED_DONT_USE_KERBEROS) { 159 use_spnego_principal = false; 160 } 161 162 cli_credentials_set_kerberos_state(auth_generic_state->credentials, 163 krb5_state); 164 165 if (target_service != NULL) { 166 nt_status = gensec_set_target_service( 167 auth_generic_state->gensec_security, 168 target_service); 169 if (!NT_STATUS_IS_OK(nt_status)) { 170 return ADS_ERROR_NT(nt_status); 171 } 172 } 173 174 if (target_hostname != NULL) { 175 nt_status = gensec_set_target_hostname( 176 auth_generic_state->gensec_security, 177 target_hostname); 178 if (!NT_STATUS_IS_OK(nt_status)) { 179 return ADS_ERROR_NT(nt_status); 180 } 181 } 182 183 if (target_service != NULL && target_hostname != NULL) { 184 use_spnego_principal = false; 161 185 } 162 186 163 187 switch (ads->ldap.wrap_type) { 164 188 case ADS_SASLWRAP_TYPE_SEAL: 165 features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL; 189 gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN); 190 gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SEAL); 166 191 break; 167 192 case ADS_SASLWRAP_TYPE_SIGN: 168 193 if (ads->auth.flags & ADS_AUTH_SASL_FORCE) { 169 features = NTLMSSP_FEATURE_SIGN;194 gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN); 170 195 } else { 171 196 /* 172 197 * windows servers are broken with sign only, 173 * so we need to use seal here too 198 * so we let the NTLMSSP backend to seal here, 199 * via GENSEC_FEATURE_LDAP_STYLE. 174 200 */ 175 features = NTLMSSP_FEATURE_SIGN | NTLMSSP_FEATURE_SEAL;176 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL;201 gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_SIGN); 202 gensec_want_feature(auth_generic_state->gensec_security, GENSEC_FEATURE_LDAP_STYLE); 177 203 } 178 204 break; … … 181 207 } 182 208 183 ntlmssp_want_feature(ntlmssp_state, features); 184 185 blob_in = data_blob_null; 186 187 do { 188 nt_status = ntlmssp_update(ntlmssp_state, 189 blob_in, &blob_out); 209 nt_status = auth_generic_client_start_by_sasl(auth_generic_state, 210 sasl_list); 211 if (!NT_STATUS_IS_OK(nt_status)) { 212 return ADS_ERROR_NT(nt_status); 213 } 214 215 rc = LDAP_SASL_BIND_IN_PROGRESS; 216 nt_status = NT_STATUS_MORE_PROCESSING_REQUIRED; 217 if (use_spnego_principal) { 218 blob_in = data_blob_dup_talloc(talloc_tos(), server_blob); 219 if (blob_in.length == 0) { 220 TALLOC_FREE(auth_generic_state); 221 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); 222 } 223 } else { 224 blob_in = data_blob_null; 225 } 226 blob_out = data_blob_null; 227 228 while (true) { 229 struct berval cred, *scred = NULL; 230 231 nt_status = gensec_update(auth_generic_state->gensec_security, 232 talloc_tos(), blob_in, &blob_out); 190 233 data_blob_free(&blob_in); 191 if ((NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) 192 || NT_STATUS_IS_OK(nt_status)) 193 && blob_out.length) { 194 if (turn == 1) { 195 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL}; 196 /* and wrap it in a SPNEGO wrapper */ 197 msg1 = spnego_gen_negTokenInit(talloc_tos(), 198 OIDs_ntlm, &blob_out, NULL); 199 } else { 200 /* wrap it in SPNEGO */ 201 msg1 = spnego_gen_auth(talloc_tos(), blob_out); 202 } 203 204 data_blob_free(&blob_out); 205 206 cred.bv_val = (char *)msg1.data; 207 cred.bv_len = msg1.length; 208 scred = NULL; 209 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred); 210 data_blob_free(&msg1); 211 if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) { 212 if (scred) { 213 ber_bvfree(scred); 214 } 215 216 TALLOC_FREE(ntlmssp_state); 217 return ADS_ERROR(rc); 218 } 219 if (scred) { 220 blob = data_blob(scred->bv_val, scred->bv_len); 221 ber_bvfree(scred); 222 } else { 223 blob = data_blob_null; 224 } 225 226 } else { 227 228 TALLOC_FREE(ntlmssp_state); 234 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) 235 && !NT_STATUS_IS_OK(nt_status)) 236 { 237 TALLOC_FREE(auth_generic_state); 229 238 data_blob_free(&blob_out); 230 239 return ADS_ERROR_NT(nt_status); 231 240 } 232 233 if ((turn == 1) && 234 (rc == LDAP_SASL_BIND_IN_PROGRESS)) { 235 DATA_BLOB tmp_blob = data_blob_null; 236 /* the server might give us back two challenges */ 237 if (!spnego_parse_challenge(talloc_tos(), blob, &blob_in, 238 &tmp_blob)) { 239 240 TALLOC_FREE(ntlmssp_state); 241 data_blob_free(&blob); 242 DEBUG(3,("Failed to parse challenges\n")); 243 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); 241 242 if (NT_STATUS_IS_OK(nt_status) && rc == 0 && blob_out.length == 0) { 243 break; 244 } 245 246 cred.bv_val = (char *)blob_out.data; 247 cred.bv_len = blob_out.length; 248 scred = NULL; 249 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, sasl, &cred, NULL, NULL, &scred); 250 data_blob_free(&blob_out); 251 if ((rc != LDAP_SASL_BIND_IN_PROGRESS) && (rc != 0)) { 252 if (scred) { 253 ber_bvfree(scred); 244 254 } 245 data_blob_free(&tmp_blob); 246 } else if (rc == LDAP_SASL_BIND_IN_PROGRESS) { 247 if (!spnego_parse_auth_response(talloc_tos(), blob, nt_status, OID_NTLMSSP, 248 &blob_in)) { 249 250 TALLOC_FREE(ntlmssp_state); 251 data_blob_free(&blob); 252 DEBUG(3,("Failed to parse auth response\n")); 253 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); 255 256 TALLOC_FREE(auth_generic_state); 257 return ADS_ERROR(rc); 258 } 259 if (scred) { 260 blob_in = data_blob_talloc(talloc_tos(), 261 scred->bv_val, 262 scred->bv_len); 263 if (blob_in.length != scred->bv_len) { 264 ber_bvfree(scred); 265 TALLOC_FREE(auth_generic_state); 266 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); 254 267 } 255 } 256 data_blob_free(&blob); 257 data_blob_free(&blob_out); 258 turn++; 259 } while (rc == LDAP_SASL_BIND_IN_PROGRESS && !NT_STATUS_IS_OK(nt_status)); 260 261 /* we have a reference conter on ntlmssp_state, if we are signing 262 then the state will be kept by the signing engine */ 268 ber_bvfree(scred); 269 } else { 270 blob_in = data_blob_null; 271 } 272 if (NT_STATUS_IS_OK(nt_status) && rc == 0 && blob_in.length == 0) { 273 break; 274 } 275 } 276 277 data_blob_free(&blob_in); 278 data_blob_free(&blob_out); 263 279 264 280 if (ads->ldap.wrap_type >= ADS_SASLWRAP_TYPE_SEAL) { 265 281 bool ok; 266 282 267 ok = ntlmssp_have_feature(ntlmssp_state,268 NTLMSSP_FEATURE_SEAL);283 ok = gensec_have_feature(auth_generic_state->gensec_security, 284 GENSEC_FEATURE_SEAL); 269 285 if (!ok) { 270 DEBUG(0,("The ntlmsspfeature sealing request, but unavailable\n"));271 TALLOC_FREE( ntlmssp_state);286 DEBUG(0,("The gensec feature sealing request, but unavailable\n")); 287 TALLOC_FREE(auth_generic_state); 272 288 return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE); 273 289 } 274 290 275 ok = ntlmssp_have_feature(ntlmssp_state,276 NTLMSSP_FEATURE_SIGN);291 ok = gensec_have_feature(auth_generic_state->gensec_security, 292 GENSEC_FEATURE_SIGN); 277 293 if (!ok) { 278 DEBUG(0,("The ntlmsspfeature signing request, but unavailable\n"));279 TALLOC_FREE( ntlmssp_state);294 DEBUG(0,("The gensec feature signing request, but unavailable\n")); 295 TALLOC_FREE(auth_generic_state); 280 296 return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE); 281 297 } … … 284 300 bool ok; 285 301 286 ok = ntlmssp_have_feature(ntlmssp_state,287 NTLMSSP_FEATURE_SIGN);302 ok = gensec_have_feature(auth_generic_state->gensec_security, 303 GENSEC_FEATURE_SIGN); 288 304 if (!ok) { 289 305 DEBUG(0,("The gensec feature signing request, but unavailable\n")); 290 TALLOC_FREE( ntlmssp_state);306 TALLOC_FREE(auth_generic_state); 291 307 return ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE); 292 308 } 293 309 } 294 310 311 ads->auth.tgs_expire = LONG_MAX; 312 end_nt_time = gensec_expire_time(auth_generic_state->gensec_security); 313 if (end_nt_time != GENSEC_EXPIRE_TIME_INFINITY) { 314 struct timeval tv; 315 nttime_to_timeval(&tv, end_nt_time); 316 ads->auth.tgs_expire = tv.tv_sec; 317 } 318 295 319 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) { 296 ads->ldap.out.max_unwrapped = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED - NTLMSSP_SIG_SIZE; 297 ads->ldap.out.sig_size = NTLMSSP_SIG_SIZE; 298 ads->ldap.in.min_wrapped = ads->ldap.out.sig_size; 320 size_t max_wrapped = gensec_max_wrapped_size(auth_generic_state->gensec_security); 321 ads->ldap.out.max_unwrapped = gensec_max_input_size(auth_generic_state->gensec_security); 322 323 ads->ldap.out.sig_size = max_wrapped - ads->ldap.out.max_unwrapped; 324 /* 325 * Note that we have to truncate this to 0x2C 326 * (taken from a capture with LDAP unbind), as the 327 * signature size is not constant for Kerberos with 328 * arcfour-hmac-md5. 329 */ 330 ads->ldap.in.min_wrapped = MIN(ads->ldap.out.sig_size, 0x2C); 299 331 ads->ldap.in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED; 300 status = ads_setup_sasl_wrapping(ads, &ads_sasl_ ntlmssp_ops, ntlmssp_state);332 status = ads_setup_sasl_wrapping(ads, &ads_sasl_gensec_ops, auth_generic_state->gensec_security); 301 333 if (!ADS_ERR_OK(status)) { 302 334 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n", 303 335 ads_errstr(status))); 304 TALLOC_FREE( ntlmssp_state);336 TALLOC_FREE(auth_generic_state); 305 337 return status; 306 338 } 307 } else { 308 TALLOC_FREE(ntlmssp_state); 309 } 339 /* Only keep the gensec_security element around long-term */ 340 talloc_steal(NULL, auth_generic_state->gensec_security); 341 } 342 TALLOC_FREE(auth_generic_state); 310 343 311 344 return ADS_ERROR(rc); 312 345 } 313 346 314 #ifdef HAVE_GSSAPI 315 static ADS_STATUS ads_sasl_gssapi_wrap(ADS_STRUCT *ads, uint8 *buf, uint32 len) 347 #ifdef HAVE_KRB5 348 static ADS_STATUS ads_init_gssapi_cred(ADS_STRUCT *ads, gss_cred_id_t *cred) 349 { 350 ADS_STATUS status; 351 krb5_context kctx; 352 krb5_error_code kerr; 353 krb5_ccache kccache = NULL; 354 uint32_t maj, min; 355 356 *cred = GSS_C_NO_CREDENTIAL; 357 358 if (!ads->auth.ccache_name) { 359 return ADS_SUCCESS; 360 } 361 362 kerr = krb5_init_context(&kctx); 363 if (kerr) { 364 return ADS_ERROR_KRB5(kerr); 365 } 366 367 #ifdef HAVE_GSS_KRB5_IMPORT_CRED 368 kerr = krb5_cc_resolve(kctx, ads->auth.ccache_name, &kccache); 369 if (kerr) { 370 status = ADS_ERROR_KRB5(kerr); 371 goto done; 372 } 373 374 maj = gss_krb5_import_cred(&min, kccache, NULL, NULL, cred); 375 if (maj != GSS_S_COMPLETE) { 376 status = ADS_ERROR_GSS(maj, min); 377 goto done; 378 } 379 #else 380 /* We need to fallback to overriding the default creds. 381 * This operation is not thread safe as it changes the process 382 * environment variable, but we do not have any better option 383 * with older kerberos libraries */ 384 { 385 const char *oldccname = NULL; 386 387 oldccname = getenv("KRB5CCNAME"); 388 setenv("KRB5CCNAME", ads->auth.ccache_name, 1); 389 390 maj = gss_acquire_cred(&min, GSS_C_NO_NAME, GSS_C_INDEFINITE, 391 NULL, GSS_C_INITIATE, cred, NULL, NULL); 392 393 if (oldccname) { 394 setenv("KRB5CCNAME", oldccname, 1); 395 } else { 396 unsetenv("KRB5CCNAME"); 397 } 398 399 if (maj != GSS_S_COMPLETE) { 400 status = ADS_ERROR_GSS(maj, min); 401 goto done; 402 } 403 } 404 #endif 405 406 status = ADS_SUCCESS; 407 408 done: 409 if (!ADS_ERR_OK(status) && kccache != NULL) { 410 krb5_cc_close(kctx, kccache); 411 } 412 krb5_free_context(kctx); 413 return status; 414 } 415 416 static ADS_STATUS ads_sasl_gssapi_wrap(ADS_STRUCT *ads, uint8_t *buf, uint32_t len) 316 417 { 317 418 gss_ctx_id_t context_handle = (gss_ctx_id_t)ads->ldap.wrap_private_data; 318 419 ADS_STATUS status; 319 420 int gss_rc; 320 uint32 minor_status;421 uint32_t minor_status; 321 422 gss_buffer_desc unwrapped, wrapped; 322 423 int conf_req_flag, conf_state; … … 359 460 ADS_STATUS status; 360 461 int gss_rc; 361 uint32 minor_status;462 uint32_t minor_status; 362 463 gss_buffer_desc unwrapped, wrapped; 363 464 int conf_state; … … 395 496 { 396 497 gss_ctx_id_t context_handle = (gss_ctx_id_t)ads->ldap.wrap_private_data; 397 uint32 minor_status;498 uint32_t minor_status; 398 499 399 500 gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER); … … 410 511 }; 411 512 412 /* 413 perform a LDAP/SASL/SPNEGO/GSSKRB5 bind 414 */ 415 static ADS_STATUS ads_sasl_spnego_gsskrb5_bind(ADS_STRUCT *ads, const gss_name_t serv_name) 416 { 417 ADS_STATUS status; 418 bool ok; 419 uint32 minor_status; 420 int gss_rc, rc; 421 gss_OID_desc krb5_mech_type = 422 {9, CONST_DISCARD(char *, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") }; 423 gss_OID mech_type = &krb5_mech_type; 424 gss_OID actual_mech_type = GSS_C_NULL_OID; 425 const char *spnego_mechs[] = {OID_KERBEROS5_OLD, OID_KERBEROS5, OID_NTLMSSP, NULL}; 426 gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT; 427 gss_buffer_desc input_token, output_token; 428 uint32 req_flags, ret_flags; 429 uint32 req_tmp, ret_tmp; 430 DATA_BLOB unwrapped; 431 DATA_BLOB wrapped; 432 struct berval cred, *scred = NULL; 433 434 input_token.value = NULL; 435 input_token.length = 0; 436 437 req_flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG; 438 switch (ads->ldap.wrap_type) { 439 case ADS_SASLWRAP_TYPE_SEAL: 440 req_flags |= GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG; 441 break; 442 case ADS_SASLWRAP_TYPE_SIGN: 443 req_flags |= GSS_C_INTEG_FLAG; 444 break; 445 case ADS_SASLWRAP_TYPE_PLAIN: 446 break; 447 } 448 449 /* Note: here we explicit ask for the krb5 mech_type */ 450 gss_rc = gss_init_sec_context(&minor_status, 451 GSS_C_NO_CREDENTIAL, 452 &context_handle, 453 serv_name, 454 mech_type, 455 req_flags, 456 0, 457 NULL, 458 &input_token, 459 &actual_mech_type, 460 &output_token, 461 &ret_flags, 462 NULL); 463 if (gss_rc && gss_rc != GSS_S_CONTINUE_NEEDED) { 464 status = ADS_ERROR_GSS(gss_rc, minor_status); 465 goto failed; 466 } 467 468 /* 469 * As some gssapi krb5 mech implementations 470 * automaticly add GSS_C_INTEG_FLAG and GSS_C_CONF_FLAG 471 * to req_flags internaly, it's not possible to 472 * use plain or signing only connection via 473 * the gssapi interface. 474 * 475 * Because of this we need to check it the ret_flags 476 * has more flags as req_flags and correct the value 477 * of ads->ldap.wrap_type. 478 * 479 * I ads->auth.flags has ADS_AUTH_SASL_FORCE 480 * we need to give an error. 481 */ 482 req_tmp = req_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG); 483 ret_tmp = ret_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG); 484 485 if (req_tmp == ret_tmp) { 486 /* everythings fine... */ 487 488 } else if (req_flags & GSS_C_CONF_FLAG) { 489 /* 490 * here we wanted sealing but didn't got it 491 * from the gssapi library 492 */ 493 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED); 494 goto failed; 495 496 } else if ((req_flags & GSS_C_INTEG_FLAG) && 497 !(ret_flags & GSS_C_INTEG_FLAG)) { 498 /* 499 * here we wanted siging but didn't got it 500 * from the gssapi library 501 */ 502 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED); 503 goto failed; 504 505 } else if (ret_flags & GSS_C_CONF_FLAG) { 506 /* 507 * here we didn't want sealing 508 * but the gssapi library forces it 509 * so correct the needed wrap_type if 510 * the caller didn't forced siging only 511 */ 512 if (ads->auth.flags & ADS_AUTH_SASL_FORCE) { 513 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED); 514 goto failed; 515 } 516 517 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SEAL; 518 req_flags = ret_flags; 519 520 } else if (ret_flags & GSS_C_INTEG_FLAG) { 521 /* 522 * here we didn't want signing 523 * but the gssapi library forces it 524 * so correct the needed wrap_type if 525 * the caller didn't forced plain 526 */ 527 if (ads->auth.flags & ADS_AUTH_SASL_FORCE) { 528 status = ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED); 529 goto failed; 530 } 531 532 ads->ldap.wrap_type = ADS_SASLWRAP_TYPE_SIGN; 533 req_flags = ret_flags; 534 } else { 535 /* 536 * This could (should?) not happen 537 */ 538 status = ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR); 539 goto failed; 540 541 } 542 543 /* and wrap that in a shiny SPNEGO wrapper */ 544 unwrapped = data_blob_const(output_token.value, output_token.length); 545 wrapped = spnego_gen_negTokenInit(talloc_tos(), 546 spnego_mechs, &unwrapped, NULL); 547 gss_release_buffer(&minor_status, &output_token); 548 if (unwrapped.length > wrapped.length) { 549 status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); 550 goto failed; 551 } 552 553 cred.bv_val = (char *)wrapped.data; 554 cred.bv_len = wrapped.length; 555 556 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, 557 &scred); 558 data_blob_free(&wrapped); 559 if (rc != LDAP_SUCCESS) { 560 status = ADS_ERROR(rc); 561 goto failed; 562 } 563 564 if (scred) { 565 wrapped = data_blob_const(scred->bv_val, scred->bv_len); 566 } else { 567 wrapped = data_blob_null; 568 } 569 570 ok = spnego_parse_auth_response(talloc_tos(), wrapped, NT_STATUS_OK, 571 OID_KERBEROS5_OLD, 572 &unwrapped); 573 if (scred) ber_bvfree(scred); 574 if (!ok) { 575 status = ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE); 576 goto failed; 577 } 578 579 input_token.value = unwrapped.data; 580 input_token.length = unwrapped.length; 581 582 /* 583 * As we asked for mutal authentication 584 * we need to pass the servers response 585 * to gssapi 586 */ 587 gss_rc = gss_init_sec_context(&minor_status, 588 GSS_C_NO_CREDENTIAL, 589 &context_handle, 590 serv_name, 591 mech_type, 592 req_flags, 593 0, 594 NULL, 595 &input_token, 596 &actual_mech_type, 597 &output_token, 598 &ret_flags, 599 NULL); 600 data_blob_free(&unwrapped); 601 if (gss_rc) { 602 status = ADS_ERROR_GSS(gss_rc, minor_status); 603 goto failed; 604 } 605 606 gss_release_buffer(&minor_status, &output_token); 607 608 /* 609 * If we the sign and seal options 610 * doesn't match after getting the response 611 * from the server, we don't want to use the connection 612 */ 613 req_tmp = req_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG); 614 ret_tmp = ret_flags & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG); 615 616 if (req_tmp != ret_tmp) { 617 /* everythings fine... */ 618 status = ADS_ERROR_NT(NT_STATUS_INVALID_NETWORK_RESPONSE); 619 goto failed; 620 } 621 622 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) { 623 uint32 max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED; 624 625 gss_rc = gss_wrap_size_limit(&minor_status, context_handle, 626 (ads->ldap.wrap_type == ADS_SASLWRAP_TYPE_SEAL), 627 GSS_C_QOP_DEFAULT, 628 max_msg_size, &ads->ldap.out.max_unwrapped); 629 if (gss_rc) { 630 status = ADS_ERROR_GSS(gss_rc, minor_status); 631 goto failed; 632 } 633 634 ads->ldap.out.sig_size = max_msg_size - ads->ldap.out.max_unwrapped; 635 ads->ldap.in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */ 636 ads->ldap.in.max_wrapped = max_msg_size; 637 status = ads_setup_sasl_wrapping(ads, &ads_sasl_gssapi_ops, context_handle); 638 if (!ADS_ERR_OK(status)) { 639 DEBUG(0, ("ads_setup_sasl_wrapping() failed: %s\n", 640 ads_errstr(status))); 641 goto failed; 642 } 643 /* make sure we don't free context_handle */ 644 context_handle = GSS_C_NO_CONTEXT; 645 } 646 647 status = ADS_SUCCESS; 648 649 failed: 650 if (context_handle != GSS_C_NO_CONTEXT) 651 gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER); 652 return status; 653 } 654 655 #endif /* HAVE_GSSAPI */ 513 #endif /* HAVE_KRB5 */ 656 514 657 515 #ifdef HAVE_KRB5 658 516 struct ads_service_principal { 659 char *string; 660 #ifdef HAVE_GSSAPI 661 gss_name_t name; 517 char *service; 518 char *hostname; 519 char *string; 520 #ifdef HAVE_KRB5 521 gss_name_t name; 662 522 #endif 663 523 }; … … 665 525 static void ads_free_service_principal(struct ads_service_principal *p) 666 526 { 527 SAFE_FREE(p->service); 528 SAFE_FREE(p->hostname); 667 529 SAFE_FREE(p->string); 668 530 669 #ifdef HAVE_ GSSAPI531 #ifdef HAVE_KRB5 670 532 if (p->name) { 671 uint32 minor_status;533 uint32_t minor_status; 672 534 gss_release_name(&minor_status, &p->name); 673 535 } … … 676 538 } 677 539 678 679 static ADS_STATUS ads_guess_service_principal(ADS_STRUCT *ads, 680 char **returned_principal) 681 { 540 static ADS_STATUS ads_guess_target(ADS_STRUCT *ads, 541 char **service, 542 char **hostname, 543 char **principal) 544 { 545 ADS_STATUS status = ADS_ERROR(LDAP_NO_MEMORY); 682 546 char *princ = NULL; 547 TALLOC_CTX *frame; 548 char *server = NULL; 549 char *realm = NULL; 550 int rc; 551 552 frame = talloc_stackframe(); 553 if (frame == NULL) { 554 return ADS_ERROR(LDAP_NO_MEMORY); 555 } 683 556 684 557 if (ads->server.realm && ads->server.ldap_server) { 685 char *server, *server_realm; 686 687 server = SMB_STRDUP(ads->server.ldap_server); 688 server_realm = SMB_STRDUP(ads->server.realm); 689 690 if (!server || !server_realm) { 691 SAFE_FREE(server); 692 SAFE_FREE(server_realm); 693 return ADS_ERROR(LDAP_NO_MEMORY); 694 } 695 696 strlower_m(server); 697 strupper_m(server_realm); 698 if (asprintf(&princ, "ldap/%s@%s", server, server_realm) == -1) { 699 SAFE_FREE(server); 700 SAFE_FREE(server_realm); 701 return ADS_ERROR(LDAP_NO_MEMORY); 702 } 703 704 SAFE_FREE(server); 705 SAFE_FREE(server_realm); 706 707 if (!princ) { 708 return ADS_ERROR(LDAP_NO_MEMORY); 558 server = strlower_talloc(frame, ads->server.ldap_server); 559 if (server == NULL) { 560 goto out; 561 } 562 563 realm = strupper_talloc(frame, ads->server.realm); 564 if (realm == NULL) { 565 goto out; 566 } 567 568 /* 569 * If we got a name which is bigger than a NetBIOS name, 570 * but isn't a FQDN, create one. 571 */ 572 if (strlen(server) > 15 && strstr(server, ".") == NULL) { 573 char *dnsdomain; 574 575 dnsdomain = strlower_talloc(frame, ads->server.realm); 576 if (dnsdomain == NULL) { 577 goto out; 578 } 579 580 server = talloc_asprintf(frame, 581 "%s.%s", 582 server, dnsdomain); 583 if (server == NULL) { 584 goto out; 585 } 709 586 } 710 587 } else if (ads->config.realm && ads->config.ldap_server_name) { 711 char *server, *server_realm; 712 713 server = SMB_STRDUP(ads->config.ldap_server_name); 714 server_realm = SMB_STRDUP(ads->config.realm); 715 716 if (!server || !server_realm) { 717 SAFE_FREE(server); 718 SAFE_FREE(server_realm); 719 return ADS_ERROR(LDAP_NO_MEMORY); 720 } 721 722 strlower_m(server); 723 strupper_m(server_realm); 724 if (asprintf(&princ, "ldap/%s@%s", server, server_realm) == -1) { 725 SAFE_FREE(server); 726 SAFE_FREE(server_realm); 727 return ADS_ERROR(LDAP_NO_MEMORY); 728 } 729 730 SAFE_FREE(server); 731 SAFE_FREE(server_realm); 732 733 if (!princ) { 734 return ADS_ERROR(LDAP_NO_MEMORY); 735 } 736 } 737 738 if (!princ) { 739 return ADS_ERROR(LDAP_PARAM_ERROR); 740 } 741 742 *returned_principal = princ; 743 744 return ADS_SUCCESS; 588 server = strlower_talloc(frame, ads->config.ldap_server_name); 589 if (server == NULL) { 590 goto out; 591 } 592 593 realm = strupper_talloc(frame, ads->config.realm); 594 if (realm == NULL) { 595 goto out; 596 } 597 598 /* 599 * If we got a name which is bigger than a NetBIOS name, 600 * but isn't a FQDN, create one. 601 */ 602 if (strlen(server) > 15 && strstr(server, ".") == NULL) { 603 char *dnsdomain; 604 605 dnsdomain = strlower_talloc(frame, ads->server.realm); 606 if (dnsdomain == NULL) { 607 goto out; 608 } 609 610 server = talloc_asprintf(frame, 611 "%s.%s", 612 server, dnsdomain); 613 if (server == NULL) { 614 goto out; 615 } 616 } 617 } 618 619 if (server == NULL || realm == NULL) { 620 goto out; 621 } 622 623 *service = SMB_STRDUP("ldap"); 624 if (*service == NULL) { 625 status = ADS_ERROR(LDAP_PARAM_ERROR); 626 goto out; 627 } 628 *hostname = SMB_STRDUP(server); 629 if (*hostname == NULL) { 630 SAFE_FREE(*service); 631 status = ADS_ERROR(LDAP_PARAM_ERROR); 632 goto out; 633 } 634 rc = asprintf(&princ, "ldap/%s@%s", server, realm); 635 if (rc == -1 || princ == NULL) { 636 SAFE_FREE(*service); 637 SAFE_FREE(*hostname); 638 status = ADS_ERROR(LDAP_PARAM_ERROR); 639 goto out; 640 } 641 642 *principal = princ; 643 644 status = ADS_SUCCESS; 645 out: 646 TALLOC_FREE(frame); 647 return status; 745 648 } 746 649 747 650 static ADS_STATUS ads_generate_service_principal(ADS_STRUCT *ads, 748 const char *given_principal,749 651 struct ads_service_principal *p) 750 652 { 751 653 ADS_STATUS status; 752 #ifdef HAVE_ GSSAPI654 #ifdef HAVE_KRB5 753 655 gss_buffer_desc input_name; 754 656 /* GSS_KRB5_NT_PRINCIPAL_NAME */ 755 657 gss_OID_desc nt_principal = 756 {10, CONST_DISCARD(char *, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01")};757 uint32 minor_status;658 {10, discard_const_p(char, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01")}; 659 uint32_t minor_status; 758 660 int gss_rc; 759 661 #endif … … 761 663 ZERO_STRUCTP(p); 762 664 763 /* I've seen a child Windows 2000 domain not send 764 the principal name back in the first round of 765 the SASL bind reply. So we guess based on server 766 name and realm. --jerry */ 767 /* Also try best guess when we get the w2k8 ignore principal 768 back, or when we are configured to ignore it - gd, 769 abartlet */ 770 771 if (!lp_client_use_spnego_principal() || 772 !given_principal || 773 strequal(given_principal, ADS_IGNORE_PRINCIPAL)) { 774 775 status = ads_guess_service_principal(ads, &p->string); 776 if (!ADS_ERR_OK(status)) { 777 return status; 778 } 779 } else { 780 p->string = SMB_STRDUP(given_principal); 781 if (!p->string) { 782 return ADS_ERROR(LDAP_NO_MEMORY); 783 } 784 } 785 786 #ifdef HAVE_GSSAPI 665 status = ads_guess_target(ads, 666 &p->service, 667 &p->hostname, 668 &p->string); 669 if (!ADS_ERR_OK(status)) { 670 return status; 671 } 672 673 #ifdef HAVE_KRB5 787 674 input_name.value = p->string; 788 675 input_name.length = strlen(p->string); … … 798 685 } 799 686 800 /*801 perform a LDAP/SASL/SPNEGO/KRB5 bind802 */803 static ADS_STATUS ads_sasl_spnego_rawkrb5_bind(ADS_STRUCT *ads, const char *principal)804 {805 DATA_BLOB blob = data_blob_null;806 struct berval cred, *scred = NULL;807 DATA_BLOB session_key = data_blob_null;808 int rc;809 810 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {811 return ADS_ERROR_NT(NT_STATUS_NOT_SUPPORTED);812 }813 814 rc = spnego_gen_krb5_negTokenInit(talloc_tos(), principal,815 ads->auth.time_offset, &blob, &session_key, 0,816 &ads->auth.tgs_expire);817 818 if (rc) {819 return ADS_ERROR_KRB5(rc);820 }821 822 /* now send the auth packet and we should be done */823 cred.bv_val = (char *)blob.data;824 cred.bv_len = blob.length;825 826 rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);827 828 data_blob_free(&blob);829 data_blob_free(&session_key);830 if(scred)831 ber_bvfree(scred);832 833 return ADS_ERROR(rc);834 }835 836 static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads,837 struct ads_service_principal *p)838 {839 #ifdef HAVE_GSSAPI840 /*841 * we only use the gsskrb5 based implementation842 * when sasl sign or seal is requested.843 *844 * This has the following reasons:845 * - it's likely that the gssapi krb5 mech implementation846 * doesn't support to negotiate plain connections847 * - the ads_sasl_spnego_rawkrb5_bind is more robust848 * against clock skew errors849 */850 if (ads->ldap.wrap_type > ADS_SASLWRAP_TYPE_PLAIN) {851 return ads_sasl_spnego_gsskrb5_bind(ads, p->name);852 }853 #endif854 return ads_sasl_spnego_rawkrb5_bind(ads, p->string);855 }856 687 #endif /* HAVE_KRB5 */ 857 688 … … 861 692 static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads) 862 693 { 694 TALLOC_CTX *frame = talloc_stackframe(); 695 struct ads_service_principal p = {0}; 863 696 struct berval *scred=NULL; 864 697 int rc, i; … … 875 708 if (rc != LDAP_SASL_BIND_IN_PROGRESS) { 876 709 status = ADS_ERROR(rc); 877 goto failed;710 goto done; 878 711 } 879 712 … … 890 723 if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &given_principal, NULL) || 891 724 OIDs[0] == NULL) { 892 data_blob_free(&blob);893 725 status = ADS_ERROR(LDAP_OPERATIONS_ERROR); 894 goto failed;895 } 896 data_blob_free(&blob);726 goto done; 727 } 728 TALLOC_FREE(given_principal); 897 729 898 730 /* make sure the server understands kerberos */ … … 907 739 talloc_free(OIDs[i]); 908 740 } 909 DEBUG(3,("ads_sasl_spnego_bind: got server principal name = %s\n", given_principal)); 741 742 status = ads_generate_service_principal(ads, &p); 743 if (!ADS_ERR_OK(status)) { 744 goto done; 745 } 910 746 911 747 #ifdef HAVE_KRB5 … … 913 749 got_kerberos_mechanism) 914 750 { 915 struct ads_service_principal p; 916 917 status = ads_generate_service_principal(ads, given_principal, &p); 918 TALLOC_FREE(given_principal); 919 if (!ADS_ERR_OK(status)) { 920 return status; 921 } 922 923 status = ads_sasl_spnego_krb5_bind(ads, &p); 751 status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO", 752 CRED_MUST_USE_KERBEROS, 753 p.service, p.hostname, 754 blob); 924 755 if (ADS_ERR_OK(status)) { 925 756 ads_free_service_principal(&p); 926 return status;927 } 928 929 DEBUG(10,("ads_sasl_spnego_ krb5_bindfailed with: %s, "757 goto done; 758 } 759 760 DEBUG(10,("ads_sasl_spnego_gensec_bind(KRB5) failed with: %s, " 930 761 "calling kinit\n", ads_errstr(status))); 931 762 … … 933 764 934 765 if (ADS_ERR_OK(status)) { 935 status = ads_sasl_spnego_krb5_bind(ads, &p); 766 status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO", 767 CRED_MUST_USE_KERBEROS, 768 p.service, p.hostname, 769 blob); 936 770 if (!ADS_ERR_OK(status)) { 937 771 DEBUG(0,("kinit succeeded but " 938 "ads_sasl_spnego_ krb5_bindfailed: %s\n",772 "ads_sasl_spnego_gensec_bind(KRB5) failed: %s\n", 939 773 ads_errstr(status))); 940 774 } 941 775 } 942 943 ads_free_service_principal(&p);944 776 945 777 /* only fallback to NTLMSSP if allowed */ 946 778 if (ADS_ERR_OK(status) || 947 779 !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) { 948 return status;949 } 950 } else780 goto done; 781 } 782 } 951 783 #endif 952 {953 TALLOC_FREE(given_principal);954 }955 784 956 785 /* lets do NTLMSSP ... this has the big advantage that we don't need 957 786 to sync clocks, and we don't rely on special versions of the krb5 958 787 library for HMAC_MD4 encryption */ 959 return ads_sasl_spnego_ntlmssp_bind(ads); 960 961 failed: 788 status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO", 789 CRED_DONT_USE_KERBEROS, 790 p.service, p.hostname, 791 data_blob_null); 792 done: 793 ads_free_service_principal(&p); 794 TALLOC_FREE(frame); 962 795 return status; 963 796 } 964 797 965 #ifdef HAVE_ GSSAPI798 #ifdef HAVE_KRB5 966 799 #define MAX_GSS_PASSES 3 967 800 … … 974 807 static ADS_STATUS ads_sasl_gssapi_do_bind(ADS_STRUCT *ads, const gss_name_t serv_name) 975 808 { 976 uint32 minor_status; 809 uint32_t minor_status; 810 gss_cred_id_t gss_cred = GSS_C_NO_CREDENTIAL; 977 811 gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT; 978 812 gss_OID mech_type = GSS_C_NULL_OID; 979 813 gss_buffer_desc output_token, input_token; 980 uint32 req_flags, ret_flags;814 uint32_t req_flags, ret_flags; 981 815 int conf_state; 982 816 struct berval cred; … … 984 818 int i=0; 985 819 int gss_rc, rc; 986 uint8 *p;987 uint32 max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED;988 uint8 wrap_type = ADS_SASLWRAP_TYPE_PLAIN;820 uint8_t *p; 821 uint32_t max_msg_size = ADS_SASL_WRAPPING_OUT_MAX_WRAPPED; 822 uint8_t wrap_type = ADS_SASLWRAP_TYPE_PLAIN; 989 823 ADS_STATUS status; 990 824 991 825 input_token.value = NULL; 992 826 input_token.length = 0; 827 828 status = ads_init_gssapi_cred(ads, &gss_cred); 829 if (!ADS_ERR_OK(status)) { 830 goto failed; 831 } 993 832 994 833 /* … … 1001 840 for (i=0; i < MAX_GSS_PASSES; i++) { 1002 841 gss_rc = gss_init_sec_context(&minor_status, 1003 GSS_C_NO_CREDENTIAL,842 gss_cred, 1004 843 &context_handle, 1005 844 serv_name, … … 1058 897 } 1059 898 1060 p = (uint8 *)output_token.value;899 p = (uint8_t *)output_token.value; 1061 900 1062 901 #if 0 … … 1096 935 goto failed; 1097 936 } 1098 p = (uint8 *)output_token.value;937 p = (uint8_t *)output_token.value; 1099 938 1100 939 RSIVAL(p,0,max_msg_size); … … 1148 987 ads->ldap.out.sig_size = max_msg_size - ads->ldap.out.max_unwrapped; 1149 988 ads->ldap.in.min_wrapped = 0x2C; /* taken from a capture with LDAP unbind */ 1150 ads->ldap.in.max_wrapped = max_msg_size;989 ads->ldap.in.max_wrapped = ADS_SASL_WRAPPING_IN_MAX_WRAPPED; 1151 990 status = ads_setup_sasl_wrapping(ads, &ads_sasl_gssapi_ops, context_handle); 1152 991 if (!ADS_ERR_OK(status)) { … … 1160 999 1161 1000 failed: 1162 1001 if (gss_cred != GSS_C_NO_CREDENTIAL) 1002 gss_release_cred(&minor_status, &gss_cred); 1163 1003 if (context_handle != GSS_C_NO_CONTEXT) 1164 1004 gss_delete_sec_context(&minor_status, &context_handle, GSS_C_NO_BUFFER); … … 1174 1014 struct ads_service_principal p; 1175 1015 1176 status = ads_generate_service_principal(ads, NULL,&p);1016 status = ads_generate_service_principal(ads, &p); 1177 1017 if (!ADS_ERR_OK(status)) { 1178 1018 return status; … … 1199 1039 } 1200 1040 1201 #endif /* HAVE_ GSSAPI*/1041 #endif /* HAVE_KRB5 */ 1202 1042 1203 1043 /* mapping between SASL mechanisms and functions */ … … 1207 1047 } sasl_mechanisms[] = { 1208 1048 {"GSS-SPNEGO", ads_sasl_spnego_bind}, 1209 #ifdef HAVE_ GSSAPI1049 #ifdef HAVE_KRB5 1210 1050 {"GSSAPI", ads_sasl_gssapi_bind}, /* doesn't work with .NET RC1. No idea why */ 1211 1051 #endif
Note:
See TracChangeset
for help on using the changeset viewer.