Changeset 988 for vendor/current/source3/libads
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- Location:
- vendor/current/source3/libads
- Files:
-
- 3 deleted
- 25 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/libads/ads_ldap_protos.h
r740 r988 25 25 #define _LIBADS_ADS_LDAP_PROTOS_H_ 26 26 27 #ifdef HAVE_LDAP_INIT_FD 28 int ldap_init_fd(ber_socket_t fd, int proto, char *uri, LDAP **ldp); 29 #endif 30 27 31 /* 28 32 * Prototypes for ads 29 33 */ 30 34 35 LDAP *ldap_open_with_timeout(const char *server, 36 struct sockaddr_storage *ss, 37 int port, unsigned int to); 31 38 void ads_msgfree(ADS_STRUCT *ads, LDAPMessage *msg); 32 39 char *ads_get_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, LDAPMessage *msg); … … 45 52 bool *more_strings); 46 53 bool ads_pull_uint32(ADS_STRUCT *ads, LDAPMessage *msg, const char *field, 47 uint32 *v);54 uint32_t *v); 48 55 bool ads_pull_guid(ADS_STRUCT *ads, LDAPMessage *msg, struct GUID *guid); 49 56 bool ads_pull_sid(ADS_STRUCT *ads, LDAPMessage *msg, const char *field, … … 55 62 char *ads_pull_username(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, 56 63 LDAPMessage *msg); 57 int ads_pull_sids_from_extendeddn(ADS_STRUCT *ads,58 TALLOC_CTX *mem_ctx,59 LDAPMessage *msg,60 const char *field,61 enum ads_extended_dn_flags flags,62 struct dom_sid **sids);63 64 64 ADS_STATUS ads_find_machine_acct(ADS_STRUCT *ads, LDAPMessage **res, 65 65 const char *machine); … … 121 121 struct GROUP_POLICY_OBJECT *gpo); 122 122 ADS_STATUS ads_search_retry_dn_sd_flags(ADS_STRUCT *ads, LDAPMessage **res, 123 uint32 sd_flags,123 uint32_t sd_flags, 124 124 const char *dn, 125 125 const char **attrs); 126 126 ADS_STATUS ads_do_search_all_sd_flags(ADS_STRUCT *ads, const char *bind_path, 127 127 int scope, const char *expr, 128 const char **attrs, uint32 sd_flags,128 const char **attrs, uint32_t sd_flags, 129 129 LDAPMessage **res); 130 130 ADS_STATUS ads_get_tokensids(ADS_STRUCT *ads, -
vendor/current/source3/libads/ads_proto.h
r740 r988 59 59 /* The following definitions come from libads/kerberos_util.c */ 60 60 61 ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads,62 const char *machine_account,63 const char *password);64 61 int ads_kinit_password(ADS_STRUCT *ads); 65 62 … … 70 67 ADS_STATUS ads_connect(ADS_STRUCT *ads); 71 68 ADS_STATUS ads_connect_user_creds(ADS_STRUCT *ads); 72 ADS_STATUS ads_connect_gc(ADS_STRUCT *ads);73 69 void ads_disconnect(ADS_STRUCT *ads); 74 70 ADS_STATUS ads_do_search_all_fn(ADS_STRUCT *ads, const char *bind_path, … … 89 85 ADS_STATUS ads_add_strlist(TALLOC_CTX *ctx, ADS_MODLIST *mods, 90 86 const char *name, const char **vals); 91 uint32 ads_get_kvno(ADS_STRUCT *ads, const char *account_name);87 uint32_t ads_get_kvno(ADS_STRUCT *ads, const char *account_name); 92 88 uint32_t ads_get_machine_kvno(ADS_STRUCT *ads, const char *machine_name); 89 90 bool ads_element_in_array(const char **el_array, size_t num_el, const char *el); 91 92 ADS_STATUS ads_get_service_principal_names(TALLOC_CTX *mem_ctx, 93 ADS_STRUCT *ads, 94 const char *machine_name, 95 char ***spn_array, 96 size_t *num_spns); 93 97 ADS_STATUS ads_clear_service_principal_names(ADS_STRUCT *ads, const char *machine_name); 94 98 ADS_STATUS ads_add_service_principal_name(ADS_STRUCT *ads, const char *machine_name, 95 99 const char *my_fqdn, const char *spn); 96 ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, const char *machine_name, 97 const char *org_unit); 100 ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, 101 const char *machine_name, 102 const char *org_unit, 103 uint32_t etype_list); 98 104 ADS_STATUS ads_move_machine_acct(ADS_STRUCT *ads, const char *machine_name, 99 105 const char *org_unit, bool *moved); 100 106 int ads_count_replies(ADS_STRUCT *ads, void *res); 101 ADS_STATUS ads_USN(ADS_STRUCT *ads, uint32 *usn);107 ADS_STATUS ads_USN(ADS_STRUCT *ads, uint32_t *usn); 102 108 ADS_STATUS ads_current_time(ADS_STRUCT *ads); 103 ADS_STATUS ads_domain_func_level(ADS_STRUCT *ads, uint32 *val);109 ADS_STATUS ads_domain_func_level(ADS_STRUCT *ads, uint32_t *val); 104 110 ADS_STATUS ads_domain_sid(ADS_STRUCT *ads, struct dom_sid *sid); 105 111 ADS_STATUS ads_site_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char **site_name); … … 118 124 char* ads_get_samaccountname( ADS_STRUCT *ads, TALLOC_CTX *ctx, const char *machine_name ); 119 125 ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *machine_name, 120 uint32 account_type, const char *org_unit);126 uint32_t account_type, const char *org_unit); 121 127 ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname); 122 128 ADS_STATUS ads_find_samaccount(ADS_STRUCT *ads, 123 129 TALLOC_CTX *mem_ctx, 124 130 const char *samaccountname, 125 uint32 *uac_ret,131 uint32_t *uac_ret, 126 132 const char **dn_ret); 127 133 ADS_STATUS ads_config_path(ADS_STRUCT *ads, -
vendor/current/source3/libads/ads_status.c
r746 r988 23 23 #include "includes.h" 24 24 #include "smb_krb5.h" 25 #include "system/gssapi.h" 25 26 #include "smb_ldap.h" 26 27 #include "libads/ads_status.h" … … 116 117 case ENUM_ADS_ERROR_KRB5: 117 118 return error_message(status.err.rc); 118 #endif119 #ifdef HAVE_GSSAPI120 119 case ENUM_ADS_ERROR_GSS: 121 120 { 122 121 char *ret; 123 uint32 msg_ctx;124 uint32 minor;122 uint32_t msg_ctx; 123 uint32_t minor; 125 124 gss_buffer_desc msg1, msg2; 126 125 … … 148 147 } 149 148 150 #ifdef HAVE_ GSSAPI151 NTSTATUS gss_err_to_ntstatus(uint32 maj, uint32min)149 #ifdef HAVE_KRB5 150 NTSTATUS gss_err_to_ntstatus(uint32_t maj, uint32_t min) 152 151 { 153 152 ADS_STATUS adss = ADS_ERROR_GSS(maj, min); -
vendor/current/source3/libads/ads_status.h
r740 r988 64 64 NTSTATUS ads_ntstatus(ADS_STATUS status); 65 65 const char *ads_errstr(ADS_STATUS status); 66 NTSTATUS gss_err_to_ntstatus(uint32 maj, uint32min);66 NTSTATUS gss_err_to_ntstatus(uint32_t maj, uint32_t min); 67 67 68 68 #endif /* _LIBADS_ADS_STATUS_H_ */ -
vendor/current/source3/libads/ads_struct.c
r746 r988 53 53 } 54 54 55 strlcpy(ret,field, len); 55 if (strlcpy(ret,field, len) >= len) { 56 /* Truncate ! */ 57 free(r); 58 free(ret); 59 return NULL; 60 } 56 61 p=strtok_r(r, sep, &saveptr); 57 62 if (p) { 58 strlcat(ret, p, len); 63 if (strlcat(ret, p, len) >= len) { 64 free(r); 65 free(ret); 66 return NULL; 67 } 59 68 60 69 while ((p=strtok_r(NULL, sep, &saveptr)) != NULL) { … … 102 111 } 103 112 104 strlower_m( dnsdomain ); 113 if (!strlower_m( dnsdomain )) { 114 SAFE_FREE(dnsdomain); 115 return NULL; 116 } 117 105 118 all_string_sub( dnsdomain, "dc=", "", 0); 106 119 all_string_sub( dnsdomain, ",", ".", 0 ); … … 132 145 ads->server.ldap_server = ldap_server? SMB_STRDUP(ldap_server) : NULL; 133 146 134 /* we need to know if this is a foreign realm */135 if (realm && *realm && !strequal(lp_realm(), realm)) {136 ads->server.foreign = 1;137 }138 if (workgroup && *workgroup && !strequal(lp_workgroup(), workgroup)) {139 ads->server.foreign = 1;140 }141 142 147 /* the caller will own the memory by default */ 143 148 ads->is_mine = 1; … … 150 155 ads->auth.flags = wrap_flags; 151 156 152 /* Start with a page size of 1000when the connection is new,157 /* Start with the configured page size when the connection is new, 153 158 * we will drop it by half we get a timeout. */ 154 ads->config.ldap_page_size = 1000;159 ads->config.ldap_page_size = lp_ldap_page_size(); 155 160 156 161 return ads; … … 191 196 SAFE_FREE((*ads)->auth.user_name); 192 197 SAFE_FREE((*ads)->auth.kdc_server); 198 SAFE_FREE((*ads)->auth.ccache_name); 193 199 194 200 SAFE_FREE((*ads)->config.realm); -
vendor/current/source3/libads/authdata.c
r740 r988 27 27 #include "smb_krb5.h" 28 28 #include "libads/kerberos_proto.h" 29 #include "auth/common_auth.h" 30 #include "lib/param/param.h" 31 #include "librpc/crypto/gse.h" 32 #include "auth/gensec/gensec.h" 33 #include "auth/gensec/gensec_internal.h" /* TODO: remove this */ 34 #include "../libcli/auth/spnego.h" 29 35 30 36 #ifdef HAVE_KRB5 31 37 38 #include "auth/kerberos/pac_utils.h" 39 40 struct smb_krb5_context; 41 32 42 /**************************************************************** 43 Callback to get the PAC_LOGON_INFO from the blob 33 44 ****************************************************************/ 34 35 static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx, 36 DATA_BLOB pac_data, 37 struct PAC_SIGNATURE_DATA *sig, 38 krb5_context context, 39 krb5_keyblock *keyblock) 45 static NTSTATUS kerberos_fetch_pac(struct auth4_context *auth_ctx, 46 TALLOC_CTX *mem_ctx, 47 struct smb_krb5_context *smb_krb5_context, 48 DATA_BLOB *pac_blob, 49 const char *princ_name, 50 const struct tsocket_address *remote_address, 51 uint32_t session_info_flags, 52 struct auth_session_info **session_info) 40 53 { 41 krb5_error_code ret; 42 krb5_checksum cksum; 43 krb5_keyusage usage = 0; 44 45 smb_krb5_checksum_from_pac_sig(&cksum, sig); 46 47 #ifdef HAVE_KRB5_KU_OTHER_CKSUM /* Heimdal */ 48 usage = KRB5_KU_OTHER_CKSUM; 49 #elif defined(HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM) /* MIT */ 50 usage = KRB5_KEYUSAGE_APP_DATA_CKSUM; 51 #else 52 #error UNKNOWN_KRB5_KEYUSAGE 53 #endif 54 55 ret = smb_krb5_verify_checksum(context, 56 keyblock, 57 usage, 58 &cksum, 59 pac_data.data, 60 pac_data.length); 61 62 if (ret) { 63 DEBUG(2,("check_pac_checksum: PAC Verification failed: %s (%d)\n", 64 error_message(ret), ret)); 65 return ret; 66 } 67 68 return ret; 54 TALLOC_CTX *tmp_ctx; 55 struct PAC_DATA *pac_data = NULL; 56 struct PAC_DATA_CTR *pac_data_ctr = NULL; 57 NTSTATUS status = NT_STATUS_INTERNAL_ERROR; 58 59 tmp_ctx = talloc_new(mem_ctx); 60 if (!tmp_ctx) { 61 return NT_STATUS_NO_MEMORY; 62 } 63 64 if (pac_blob != NULL) { 65 status = kerberos_decode_pac(tmp_ctx, 66 *pac_blob, 67 NULL, 68 NULL, 69 NULL, 70 NULL, 71 0, 72 &pac_data); 73 if (!NT_STATUS_IS_OK(status)) { 74 goto done; 75 } 76 77 pac_data_ctr = talloc(mem_ctx, struct PAC_DATA_CTR); 78 if (pac_data_ctr == NULL) { 79 status = NT_STATUS_NO_MEMORY; 80 goto done; 81 } 82 83 talloc_set_name_const(pac_data_ctr, "struct PAC_DATA_CTR"); 84 85 pac_data_ctr->pac_data = talloc_steal(pac_data_ctr, pac_data); 86 pac_data_ctr->pac_blob = data_blob_talloc(pac_data_ctr, 87 pac_blob->data, 88 pac_blob->length); 89 90 auth_ctx->private_data = talloc_steal(auth_ctx, pac_data_ctr); 91 } 92 93 *session_info = talloc_zero(mem_ctx, struct auth_session_info); 94 if (!*session_info) { 95 status = NT_STATUS_NO_MEMORY; 96 goto done; 97 } 98 status = NT_STATUS_OK; 99 100 done: 101 TALLOC_FREE(tmp_ctx); 102 103 return status; 69 104 } 70 105 71 /** 72 * @brief Decode a blob containing a NDR envoded PAC structure 73 * 74 * @param mem_ctx - The memory context 75 * @param pac_data_blob - The data blob containing the NDR encoded data 76 * @param context - The Kerberos Context 77 * @param service_keyblock - The Service Key used to verify the checksum 78 * @param client_principal - The client principal 79 * @param tgs_authtime - The ticket timestamp 80 * @param pac_data_out - [out] The decoded PAC 81 * 82 * @return - A NTSTATUS error code 83 */ 84 NTSTATUS decode_pac_data(TALLOC_CTX *mem_ctx, 85 DATA_BLOB *pac_data_blob, 86 krb5_context context, 87 krb5_keyblock *service_keyblock, 88 krb5_const_principal client_principal, 89 time_t tgs_authtime, 90 struct PAC_DATA **pac_data_out) 91 { 92 NTSTATUS status; 93 enum ndr_err_code ndr_err; 94 krb5_error_code ret; 95 DATA_BLOB modified_pac_blob; 96 97 NTTIME tgs_authtime_nttime; 98 krb5_principal client_principal_pac = NULL; 99 int i; 100 101 struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL; 102 struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL; 103 struct PAC_SIGNATURE_DATA *srv_sig_wipe = NULL; 104 struct PAC_SIGNATURE_DATA *kdc_sig_wipe = NULL; 105 struct PAC_LOGON_NAME *logon_name = NULL; 106 struct PAC_LOGON_INFO *logon_info = NULL; 107 struct PAC_DATA *pac_data = NULL; 108 struct PAC_DATA_RAW *pac_data_raw = NULL; 109 110 DATA_BLOB *srv_sig_blob = NULL; 111 DATA_BLOB *kdc_sig_blob = NULL; 112 113 bool bool_ret; 114 115 *pac_data_out = NULL; 116 117 pac_data = TALLOC_ZERO_P(mem_ctx, struct PAC_DATA); 118 pac_data_raw = TALLOC_ZERO_P(mem_ctx, struct PAC_DATA_RAW); 119 kdc_sig_wipe = TALLOC_ZERO_P(mem_ctx, struct PAC_SIGNATURE_DATA); 120 srv_sig_wipe = TALLOC_ZERO_P(mem_ctx, struct PAC_SIGNATURE_DATA); 121 if (!pac_data_raw || !pac_data || !kdc_sig_wipe || !srv_sig_wipe) { 122 return NT_STATUS_NO_MEMORY; 123 } 124 125 ndr_err = ndr_pull_struct_blob(pac_data_blob, pac_data, pac_data, 126 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA); 127 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 128 status = ndr_map_error2ntstatus(ndr_err); 129 DEBUG(0,("can't parse the PAC: %s\n", 130 nt_errstr(status))); 131 return status; 132 } 133 134 if (pac_data->num_buffers < 4) { 135 /* we need logon_ingo, service_key and kdc_key */ 136 DEBUG(0,("less than 4 PAC buffers\n")); 137 return NT_STATUS_INVALID_PARAMETER; 138 } 139 140 ndr_err = ndr_pull_struct_blob( 141 pac_data_blob, pac_data_raw, pac_data_raw, 142 (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW); 143 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 144 status = ndr_map_error2ntstatus(ndr_err); 145 DEBUG(0,("can't parse the PAC: %s\n", 146 nt_errstr(status))); 147 return status; 148 } 149 150 if (pac_data_raw->num_buffers < 4) { 151 /* we need logon_ingo, service_key and kdc_key */ 152 DEBUG(0,("less than 4 PAC buffers\n")); 153 return NT_STATUS_INVALID_PARAMETER; 154 } 155 156 if (pac_data->num_buffers != pac_data_raw->num_buffers) { 157 /* we need logon_ingo, service_key and kdc_key */ 158 DEBUG(0, ("misparse! PAC_DATA has %d buffers while " 159 "PAC_DATA_RAW has %d\n", pac_data->num_buffers, 160 pac_data_raw->num_buffers)); 161 return NT_STATUS_INVALID_PARAMETER; 162 } 163 164 for (i=0; i < pac_data->num_buffers; i++) { 165 struct PAC_BUFFER *data_buf = &pac_data->buffers[i]; 166 struct PAC_BUFFER_RAW *raw_buf = &pac_data_raw->buffers[i]; 167 168 if (data_buf->type != raw_buf->type) { 169 DEBUG(0, ("misparse! PAC_DATA buffer %d has type " 170 "%d while PAC_DATA_RAW has %d\n", i, 171 data_buf->type, raw_buf->type)); 172 return NT_STATUS_INVALID_PARAMETER; 173 } 174 switch (data_buf->type) { 175 case PAC_TYPE_LOGON_INFO: 176 if (!data_buf->info) { 177 break; 178 } 179 logon_info = data_buf->info->logon_info.info; 180 break; 181 case PAC_TYPE_SRV_CHECKSUM: 182 if (!data_buf->info) { 183 break; 184 } 185 srv_sig_ptr = &data_buf->info->srv_cksum; 186 srv_sig_blob = &raw_buf->info->remaining; 187 break; 188 case PAC_TYPE_KDC_CHECKSUM: 189 if (!data_buf->info) { 190 break; 191 } 192 kdc_sig_ptr = &data_buf->info->kdc_cksum; 193 kdc_sig_blob = &raw_buf->info->remaining; 194 break; 195 case PAC_TYPE_LOGON_NAME: 196 logon_name = &data_buf->info->logon_name; 197 break; 198 default: 199 break; 200 } 201 } 202 203 if (!logon_info) { 204 DEBUG(0,("PAC no logon_info\n")); 205 return NT_STATUS_INVALID_PARAMETER; 206 } 207 208 if (!logon_name) { 209 DEBUG(0,("PAC no logon_name\n")); 210 return NT_STATUS_INVALID_PARAMETER; 211 } 212 213 if (!srv_sig_ptr || !srv_sig_blob) { 214 DEBUG(0,("PAC no srv_key\n")); 215 return NT_STATUS_INVALID_PARAMETER; 216 } 217 218 if (!kdc_sig_ptr || !kdc_sig_blob) { 219 DEBUG(0,("PAC no kdc_key\n")); 220 return NT_STATUS_INVALID_PARAMETER; 221 } 222 223 /* Find and zero out the signatures, 224 * as required by the signing algorithm */ 225 226 /* We find the data blobs above, 227 * now we parse them to get at the exact portion we should zero */ 228 ndr_err = ndr_pull_struct_blob( 229 kdc_sig_blob, kdc_sig_wipe, kdc_sig_wipe, 230 (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA); 231 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 232 status = ndr_map_error2ntstatus(ndr_err); 233 DEBUG(0,("can't parse the KDC signature: %s\n", 234 nt_errstr(status))); 235 return status; 236 } 237 238 ndr_err = ndr_pull_struct_blob( 239 srv_sig_blob, srv_sig_wipe, srv_sig_wipe, 240 (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA); 241 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 242 status = ndr_map_error2ntstatus(ndr_err); 243 DEBUG(0,("can't parse the SRV signature: %s\n", 244 nt_errstr(status))); 245 return status; 246 } 247 248 /* Now zero the decoded structure */ 249 memset(kdc_sig_wipe->signature.data, 250 '\0', kdc_sig_wipe->signature.length); 251 memset(srv_sig_wipe->signature.data, 252 '\0', srv_sig_wipe->signature.length); 253 254 /* and reencode, back into the same place it came from */ 255 ndr_err = ndr_push_struct_blob( 256 kdc_sig_blob, pac_data_raw, kdc_sig_wipe, 257 (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA); 258 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 259 status = ndr_map_error2ntstatus(ndr_err); 260 DEBUG(0,("can't repack the KDC signature: %s\n", 261 nt_errstr(status))); 262 return status; 263 } 264 ndr_err = ndr_push_struct_blob( 265 srv_sig_blob, pac_data_raw, srv_sig_wipe, 266 (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA); 267 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 268 status = ndr_map_error2ntstatus(ndr_err); 269 DEBUG(0,("can't repack the SRV signature: %s\n", 270 nt_errstr(status))); 271 return status; 272 } 273 274 /* push out the whole structure, but now with zero'ed signatures */ 275 ndr_err = ndr_push_struct_blob( 276 &modified_pac_blob, pac_data_raw, pac_data_raw, 277 (ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW); 278 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 279 status = ndr_map_error2ntstatus(ndr_err); 280 DEBUG(0,("can't repack the RAW PAC: %s\n", 281 nt_errstr(status))); 282 return status; 283 } 284 285 /* verify by service_key */ 286 ret = check_pac_checksum(mem_ctx, 287 modified_pac_blob, srv_sig_ptr, 288 context, 289 service_keyblock); 290 if (ret) { 291 DEBUG(1, ("PAC Decode: Failed to verify the service " 292 "signature: %s\n", error_message(ret))); 293 return NT_STATUS_ACCESS_DENIED; 294 } 295 296 /* Convert to NT time, so as not to loose accuracy in comparison */ 297 unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime); 298 299 if (tgs_authtime_nttime != logon_name->logon_time) { 300 DEBUG(2, ("PAC Decode: " 301 "Logon time mismatch between ticket and PAC!\n")); 302 DEBUG(2, ("PAC Decode: PAC: %s\n", 303 nt_time_string(mem_ctx, logon_name->logon_time))); 304 DEBUG(2, ("PAC Decode: Ticket: %s\n", 305 nt_time_string(mem_ctx, tgs_authtime_nttime))); 306 return NT_STATUS_ACCESS_DENIED; 307 } 308 309 ret = smb_krb5_parse_name_norealm(context, 310 logon_name->account_name, 311 &client_principal_pac); 312 if (ret) { 313 DEBUG(2, ("Could not parse name from PAC: [%s]:%s\n", 314 logon_name->account_name, error_message(ret))); 315 return NT_STATUS_INVALID_PARAMETER; 316 } 317 318 bool_ret = smb_krb5_principal_compare_any_realm(context, 319 client_principal, 320 client_principal_pac); 321 322 krb5_free_principal(context, client_principal_pac); 323 324 if (!bool_ret) { 325 DEBUG(2, ("Name in PAC [%s] does not match principal name " 326 "in ticket\n", logon_name->account_name)); 327 return NT_STATUS_ACCESS_DENIED; 328 } 329 330 DEBUG(3,("Found account name from PAC: %s [%s]\n", 331 logon_info->info3.base.account_name.string, 332 logon_info->info3.base.full_name.string)); 333 334 DEBUG(10,("Successfully validated Kerberos PAC\n")); 335 336 if (DEBUGLEVEL >= 10) { 337 const char *s; 338 s = NDR_PRINT_STRUCT_STRING(mem_ctx, PAC_DATA, pac_data); 339 if (s) { 340 DEBUGADD(10,("%s\n", s)); 341 } 342 } 343 344 *pac_data_out = pac_data; 345 346 return NT_STATUS_OK; 347 } 348 349 /**************************************************************** 350 Given a username, password and other details, return the 351 PAC_LOGON_INFO (the structure containing the important user 352 information such as groups). 353 ****************************************************************/ 354 106 /* 107 * Given the username/password, do a kinit, store the ticket in 108 * cache_name if specified, and return the PAC_LOGON_INFO (the 109 * structure containing the important user information such as 110 * groups). 111 */ 355 112 NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx, 356 113 const char *name, … … 364 121 time_t renewable_time, 365 122 const char *impersonate_princ_s, 366 struct PAC_LOGON_INFO **logon_info) 123 const char *local_service, 124 struct PAC_DATA_CTR **_pac_data_ctr) 367 125 { 368 126 krb5_error_code ret; 369 127 NTSTATUS status = NT_STATUS_INVALID_PARAMETER; 370 DATA_BLOB tkt, ap_rep, sesskey1, sesskey2; 371 char *client_princ_out = NULL; 128 DATA_BLOB tkt, tkt_wrapped, ap_rep, sesskey1; 372 129 const char *auth_princ = NULL; 373 const char *local_service = NULL;374 130 const char *cc = "MEMORY:kerberos_return_pac"; 131 struct auth_session_info *session_info; 132 struct gensec_security *gensec_server_context; 133 const struct gensec_security_ops **backends; 134 struct gensec_settings *gensec_settings; 135 size_t idx = 0; 136 struct auth4_context *auth_context; 137 struct loadparm_context *lp_ctx; 138 struct PAC_DATA_CTR *pac_data_ctr = NULL; 139 140 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); 141 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); 375 142 376 143 ZERO_STRUCT(tkt); 377 144 ZERO_STRUCT(ap_rep); 378 145 ZERO_STRUCT(sesskey1); 379 ZERO_STRUCT(sesskey2);380 146 381 147 if (!name || !pass) { … … 394 160 } 395 161 NT_STATUS_HAVE_NO_MEMORY(auth_princ); 396 397 local_service = talloc_asprintf(mem_ctx, "%s$@%s",398 global_myname(), lp_realm());399 NT_STATUS_HAVE_NO_MEMORY(local_service);400 162 401 163 ret = kerberos_kinit_password_ext(auth_princ, … … 455 217 goto out; 456 218 } 457 status = ads_verify_ticket(mem_ctx, 458 lp_realm(), 459 time_offset, 460 &tkt, 461 &client_princ_out, 462 logon_info, 463 &ap_rep, 464 &sesskey2, 465 False); 219 220 /* wrap that up in a nice GSS-API wrapping */ 221 tkt_wrapped = spnego_gen_krb5_wrap(tmp_ctx, tkt, TOK_ID_KRB_AP_REQ); 222 if (tkt_wrapped.data == NULL) { 223 status = NT_STATUS_NO_MEMORY; 224 goto out; 225 } 226 227 auth_context = talloc_zero(tmp_ctx, struct auth4_context); 228 if (auth_context == NULL) { 229 status = NT_STATUS_NO_MEMORY; 230 goto out; 231 } 232 auth_context->generate_session_info_pac = kerberos_fetch_pac; 233 234 lp_ctx = loadparm_init_s3(tmp_ctx, loadparm_s3_helpers()); 235 if (lp_ctx == NULL) { 236 status = NT_STATUS_INVALID_SERVER_STATE; 237 DEBUG(10, ("loadparm_init_s3 failed\n")); 238 goto out; 239 } 240 241 gensec_settings = lpcfg_gensec_settings(tmp_ctx, lp_ctx); 242 if (gensec_settings == NULL) { 243 status = NT_STATUS_NO_MEMORY; 244 DEBUG(10, ("lpcfg_gensec_settings failed\n")); 245 goto out; 246 } 247 248 backends = talloc_zero_array(gensec_settings, 249 const struct gensec_security_ops *, 2); 250 if (backends == NULL) { 251 status = NT_STATUS_NO_MEMORY; 252 goto out; 253 } 254 gensec_settings->backends = backends; 255 256 gensec_init(); 257 258 backends[idx++] = &gensec_gse_krb5_security_ops; 259 260 status = gensec_server_start(tmp_ctx, gensec_settings, 261 auth_context, &gensec_server_context); 262 466 263 if (!NT_STATUS_IS_OK(status)) { 467 DEBUG(1,("ads_verify_ticket failed: %s\n", 468 nt_errstr(status))); 469 goto out; 470 } 471 472 if (!*logon_info) { 264 DEBUG(1, (__location__ "Failed to start server-side GENSEC to validate a Kerberos ticket: %s\n", nt_errstr(status))); 265 goto out; 266 } 267 268 talloc_unlink(tmp_ctx, lp_ctx); 269 talloc_unlink(tmp_ctx, gensec_settings); 270 talloc_unlink(tmp_ctx, auth_context); 271 272 status = gensec_start_mech_by_oid(gensec_server_context, GENSEC_OID_KERBEROS5); 273 if (!NT_STATUS_IS_OK(status)) { 274 DEBUG(1, (__location__ "Failed to start server-side GENSEC krb5 to validate a Kerberos ticket: %s\n", nt_errstr(status))); 275 goto out; 276 } 277 278 /* Do a client-server update dance */ 279 status = gensec_update(gensec_server_context, tmp_ctx, tkt_wrapped, &ap_rep); 280 if (!NT_STATUS_IS_OK(status)) { 281 DEBUG(1, ("gensec_update() failed: %s\n", nt_errstr(status))); 282 goto out; 283 } 284 285 /* Now return the PAC information to the callers. We ingore 286 * the session_info and instead pick out the PAC via the 287 * private_data on the auth_context */ 288 status = gensec_session_info(gensec_server_context, tmp_ctx, &session_info); 289 if (!NT_STATUS_IS_OK(status)) { 290 DEBUG(1, ("Unable to obtain PAC via gensec_session_info\n")); 291 goto out; 292 } 293 294 pac_data_ctr = talloc_get_type_abort(gensec_server_context->auth_context->private_data, 295 struct PAC_DATA_CTR); 296 if (pac_data_ctr == NULL) { 473 297 DEBUG(1,("no PAC\n")); 474 298 status = NT_STATUS_INVALID_PARAMETER; … … 476 300 } 477 301 302 *_pac_data_ctr = talloc_move(mem_ctx, &pac_data_ctr); 303 478 304 out: 305 talloc_free(tmp_ctx); 479 306 if (cc != cache_name) { 480 307 ads_kdestroy(cc); … … 484 311 data_blob_free(&ap_rep); 485 312 data_blob_free(&sesskey1); 486 data_blob_free(&sesskey2);487 488 TALLOC_FREE(client_princ_out);489 313 490 314 return status; -
vendor/current/source3/libads/cldap.c
r740 r988 24 24 #include "../libcli/cldap/cldap.h" 25 25 #include "../lib/tsocket/tsocket.h" 26 #include "../lib/util/tevent_ntstatus.h" 26 27 #include "libads/cldap.h" 28 29 struct cldap_multi_netlogon_state { 30 struct tevent_context *ev; 31 const struct tsocket_address * const *servers; 32 int num_servers; 33 const char *domain; 34 const char *hostname; 35 unsigned ntversion; 36 int min_servers; 37 38 struct cldap_socket **cldap; 39 struct tevent_req **subreqs; 40 int num_sent; 41 int num_received; 42 int num_good_received; 43 struct cldap_netlogon *ios; 44 struct netlogon_samlogon_response **responses; 45 }; 46 47 static void cldap_multi_netlogon_done(struct tevent_req *subreq); 48 static void cldap_multi_netlogon_next(struct tevent_req *subreq); 49 50 /* 51 * Do a parallel cldap ping to the servers. The first "min_servers" 52 * are fired directly, the remaining ones in 100msec intervals. If 53 * "min_servers" responses came in successfully, we immediately reply, 54 * not waiting for the remaining ones. 55 */ 56 57 struct tevent_req *cldap_multi_netlogon_send( 58 TALLOC_CTX *mem_ctx, struct tevent_context *ev, 59 const struct tsocket_address * const *servers, int num_servers, 60 const char *domain, const char *hostname, unsigned ntversion, 61 int min_servers) 62 { 63 struct tevent_req *req, *subreq; 64 struct cldap_multi_netlogon_state *state; 65 int i; 66 67 req = tevent_req_create(mem_ctx, &state, 68 struct cldap_multi_netlogon_state); 69 if (req == NULL) { 70 return NULL; 71 } 72 state->ev = ev; 73 state->servers = servers; 74 state->num_servers = num_servers; 75 state->domain = domain; 76 state->hostname = hostname; 77 state->ntversion = ntversion; 78 state->min_servers = min_servers; 79 80 if (min_servers > num_servers) { 81 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 82 return tevent_req_post(req, ev); 83 } 84 85 state->subreqs = talloc_zero_array(state, 86 struct tevent_req *, 87 num_servers); 88 if (tevent_req_nomem(state->subreqs, req)) { 89 return tevent_req_post(req, ev); 90 } 91 92 state->cldap = talloc_zero_array(state, 93 struct cldap_socket *, 94 num_servers); 95 if (tevent_req_nomem(state->cldap, req)) { 96 return tevent_req_post(req, ev); 97 } 98 99 state->responses = talloc_zero_array(state, 100 struct netlogon_samlogon_response *, 101 num_servers); 102 if (tevent_req_nomem(state->responses, req)) { 103 return tevent_req_post(req, ev); 104 } 105 106 state->ios = talloc_zero_array(state->responses, 107 struct cldap_netlogon, 108 num_servers); 109 if (tevent_req_nomem(state->ios, req)) { 110 return tevent_req_post(req, ev); 111 } 112 113 for (i=0; i<num_servers; i++) { 114 NTSTATUS status; 115 116 status = cldap_socket_init(state->cldap, 117 NULL, /* local_addr */ 118 state->servers[i], 119 &state->cldap[i]); 120 if (tevent_req_nterror(req, status)) { 121 return tevent_req_post(req, ev); 122 } 123 124 state->ios[i].in.dest_address = NULL; 125 state->ios[i].in.dest_port = 0; 126 state->ios[i].in.realm = domain; 127 state->ios[i].in.host = NULL; 128 state->ios[i].in.user = NULL; 129 state->ios[i].in.domain_guid = NULL; 130 state->ios[i].in.domain_sid = NULL; 131 state->ios[i].in.acct_control = 0; 132 state->ios[i].in.version = ntversion; 133 state->ios[i].in.map_response = false; 134 } 135 136 for (i=0; i<min_servers; i++) { 137 state->subreqs[i] = cldap_netlogon_send(state->subreqs, 138 state->ev, 139 state->cldap[i], 140 &state->ios[i]); 141 if (tevent_req_nomem(state->subreqs[i], req)) { 142 return tevent_req_post(req, ev); 143 } 144 tevent_req_set_callback( 145 state->subreqs[i], cldap_multi_netlogon_done, req); 146 } 147 state->num_sent = min_servers; 148 149 if (state->num_sent < state->num_servers) { 150 /* 151 * After 100 milliseconds fire the next one 152 */ 153 subreq = tevent_wakeup_send(state, state->ev, 154 timeval_current_ofs(0, 100000)); 155 if (tevent_req_nomem(subreq, req)) { 156 return tevent_req_post(req, ev); 157 } 158 tevent_req_set_callback(subreq, cldap_multi_netlogon_next, 159 req); 160 } 161 162 return req; 163 } 164 165 static void cldap_multi_netlogon_done(struct tevent_req *subreq) 166 { 167 struct tevent_req *req = tevent_req_callback_data( 168 subreq, struct tevent_req); 169 struct cldap_multi_netlogon_state *state = tevent_req_data( 170 req, struct cldap_multi_netlogon_state); 171 NTSTATUS status; 172 struct netlogon_samlogon_response *response; 173 int i; 174 175 for (i=0; i<state->num_sent; i++) { 176 if (state->subreqs[i] == subreq) { 177 break; 178 } 179 } 180 if (i == state->num_sent) { 181 /* 182 * Got a response we did not fire... 183 */ 184 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); 185 return; 186 } 187 state->subreqs[i] = NULL; 188 189 response = talloc_zero(state, struct netlogon_samlogon_response); 190 if (tevent_req_nomem(response, req)) { 191 return; 192 } 193 194 status = cldap_netlogon_recv(subreq, response, 195 &state->ios[i]); 196 TALLOC_FREE(subreq); 197 state->num_received += 1; 198 199 if (NT_STATUS_IS_OK(status)) { 200 *response = state->ios[i].out.netlogon; 201 state->responses[i] = talloc_move(state->responses, 202 &response); 203 state->num_good_received += 1; 204 } 205 206 if ((state->num_received == state->num_servers) || 207 (state->num_good_received >= state->min_servers)) { 208 tevent_req_done(req); 209 return; 210 } 211 } 212 213 static void cldap_multi_netlogon_next(struct tevent_req *subreq) 214 { 215 struct tevent_req *req = tevent_req_callback_data( 216 subreq, struct tevent_req); 217 struct cldap_multi_netlogon_state *state = tevent_req_data( 218 req, struct cldap_multi_netlogon_state); 219 bool ret; 220 221 ret = tevent_wakeup_recv(subreq); 222 TALLOC_FREE(subreq); 223 if (!ret) { 224 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); 225 return; 226 } 227 228 subreq = cldap_netlogon_send(state->subreqs, 229 state->ev, 230 state->cldap[state->num_sent], 231 &state->ios[state->num_sent]); 232 if (tevent_req_nomem(subreq, req)) { 233 return; 234 } 235 tevent_req_set_callback(subreq, cldap_multi_netlogon_done, req); 236 state->subreqs[state->num_sent] = subreq; 237 state->num_sent += 1; 238 239 if (state->num_sent < state->num_servers) { 240 /* 241 * After 100 milliseconds fire the next one 242 */ 243 subreq = tevent_wakeup_send(state, state->ev, 244 timeval_current_ofs(0, 100000)); 245 if (tevent_req_nomem(subreq, req)) { 246 return; 247 } 248 tevent_req_set_callback(subreq, cldap_multi_netlogon_next, 249 req); 250 } 251 } 252 253 NTSTATUS cldap_multi_netlogon_recv( 254 struct tevent_req *req, TALLOC_CTX *mem_ctx, 255 struct netlogon_samlogon_response ***responses) 256 { 257 struct cldap_multi_netlogon_state *state = tevent_req_data( 258 req, struct cldap_multi_netlogon_state); 259 NTSTATUS status; 260 261 if (tevent_req_is_nterror(req, &status) && 262 !NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) { 263 return status; 264 } 265 /* 266 * If we timeout, give back what we have so far 267 */ 268 *responses = talloc_move(mem_ctx, &state->responses); 269 return NT_STATUS_OK; 270 } 271 272 NTSTATUS cldap_multi_netlogon( 273 TALLOC_CTX *mem_ctx, 274 const struct tsocket_address * const *servers, 275 int num_servers, 276 const char *domain, const char *hostname, unsigned ntversion, 277 int min_servers, struct timeval timeout, 278 struct netlogon_samlogon_response ***responses) 279 { 280 struct tevent_context *ev; 281 struct tevent_req *req; 282 NTSTATUS status = NT_STATUS_NO_MEMORY; 283 284 ev = samba_tevent_context_init(talloc_tos()); 285 if (ev == NULL) { 286 goto fail; 287 } 288 req = cldap_multi_netlogon_send( 289 ev, ev, servers, num_servers, domain, hostname, ntversion, 290 min_servers); 291 if (req == NULL) { 292 goto fail; 293 } 294 if (!tevent_req_set_endtime(req, ev, timeout)) { 295 goto fail; 296 } 297 if (!tevent_req_poll_ntstatus(req, ev, &status)) { 298 goto fail; 299 } 300 status = cldap_multi_netlogon_recv(req, mem_ctx, responses); 301 fail: 302 TALLOC_FREE(ev); 303 return status; 304 } 27 305 28 306 /******************************************************************* … … 31 309 32 310 bool ads_cldap_netlogon(TALLOC_CTX *mem_ctx, 33 const char *server,311 struct sockaddr_storage *ss, 34 312 const char *realm, 35 313 uint32_t nt_version, 36 314 struct netlogon_samlogon_response **_reply) 37 315 { 38 struct cldap_socket *cldap;39 struct cldap_netlogon io;40 struct netlogon_samlogon_response *reply;41 316 NTSTATUS status; 42 struct sockaddr_storage ss;43 317 char addrstr[INET6_ADDRSTRLEN]; 44 318 const char *dest_str; 319 struct tsocket_address *dest_addr; 320 const struct tsocket_address * const *dest_addrs; 321 struct netlogon_samlogon_response **responses = NULL; 45 322 int ret; 46 struct tsocket_address *dest_addr; 47 48 if (!interpret_string_addr_prefer_ipv4(&ss, server, 0)) { 49 DEBUG(2,("Failed to resolve[%s] into an address for cldap\n", 50 server)); 51 return false; 52 } 53 dest_str = print_sockaddr(addrstr, sizeof(addrstr), &ss); 323 324 dest_str = print_sockaddr(addrstr, sizeof(addrstr), ss); 54 325 55 326 ret = tsocket_address_inet_from_strings(mem_ctx, "ip", … … 63 334 } 64 335 65 /* 66 * as we use a connected udp socket 67 */ 68 status = cldap_socket_init(mem_ctx, NULL, NULL, dest_addr, &cldap); 69 TALLOC_FREE(dest_addr); 336 dest_addrs = (const struct tsocket_address * const *)&dest_addr; 337 338 status = cldap_multi_netlogon(talloc_tos(), 339 dest_addrs, 1, 340 realm, NULL, 341 nt_version, 1, 342 timeval_current_ofs(MAX(3,lp_ldap_timeout()/2), 0), 343 &responses); 70 344 if (!NT_STATUS_IS_OK(status)) { 71 DEBUG(2,("Failed to create cldap socket to %s: %s\n", 72 dest_str, nt_errstr(status))); 73 return false; 74 } 75 76 reply = talloc(cldap, struct netlogon_samlogon_response); 77 if (!reply) { 78 goto failed; 79 } 80 81 /* 82 * as we use a connected socket, so we don't need to specify the 83 * destination 84 */ 85 io.in.dest_address = NULL; 86 io.in.dest_port = 0; 87 io.in.realm = realm; 88 io.in.host = NULL; 89 io.in.user = NULL; 90 io.in.domain_guid = NULL; 91 io.in.domain_sid = NULL; 92 io.in.acct_control = 0; 93 io.in.version = nt_version; 94 io.in.map_response = false; 95 96 status = cldap_netlogon(cldap, reply, &io); 97 if (!NT_STATUS_IS_OK(status)) { 98 DEBUG(2,("cldap_netlogon() failed: %s\n", nt_errstr(status))); 99 goto failed; 100 } 101 102 *reply = io.out.netlogon; 103 *_reply = talloc_move(mem_ctx, &reply); 104 TALLOC_FREE(cldap); 345 DEBUG(2, ("ads_cldap_netlogon: cldap_multi_netlogon " 346 "failed: %s\n", nt_errstr(status))); 347 return false; 348 } 349 if (responses[0] == NULL) { 350 DEBUG(2, ("ads_cldap_netlogon: did not get a reply\n")); 351 TALLOC_FREE(responses); 352 return false; 353 } 354 *_reply = talloc_move(mem_ctx, &responses[0]); 355 105 356 return true; 106 failed:107 TALLOC_FREE(cldap);108 return false;109 357 } 110 358 … … 114 362 115 363 bool ads_cldap_netlogon_5(TALLOC_CTX *mem_ctx, 116 const char *server,364 struct sockaddr_storage *ss, 117 365 const char *realm, 118 366 struct NETLOGON_SAM_LOGON_RESPONSE_EX *reply5) … … 122 370 bool ret; 123 371 124 ret = ads_cldap_netlogon(mem_ctx, s erver, realm, nt_version, &reply);372 ret = ads_cldap_netlogon(mem_ctx, ss, realm, nt_version, &reply); 125 373 if (!ret) { 126 374 return false; -
vendor/current/source3/libads/cldap.h
r740 r988 27 27 28 28 /* The following definitions come from libads/cldap.c */ 29 30 struct tevent_req *cldap_multi_netlogon_send( 31 TALLOC_CTX *mem_ctx, struct tevent_context *ev, 32 const struct tsocket_address * const *servers, 33 int num_servers, 34 const char *domain, const char *hostname, unsigned ntversion, 35 int min_servers); 36 NTSTATUS cldap_multi_netlogon_recv( 37 struct tevent_req *req, TALLOC_CTX *mem_ctx, 38 struct netlogon_samlogon_response ***responses); 39 NTSTATUS cldap_multi_netlogon( 40 TALLOC_CTX *mem_ctx, 41 const struct tsocket_address * const *servers, 42 int num_servers, 43 const char *domain, const char *hostname, unsigned ntversion, 44 int min_servers, struct timeval timeout, 45 struct netlogon_samlogon_response ***responses); 46 29 47 bool ads_cldap_netlogon(TALLOC_CTX *mem_ctx, 30 const char *server,48 struct sockaddr_storage *ss, 31 49 const char *realm, 32 50 uint32_t nt_version, 33 51 struct netlogon_samlogon_response **reply); 34 52 bool ads_cldap_netlogon_5(TALLOC_CTX *mem_ctx, 35 const char *server,53 struct sockaddr_storage *ss, 36 54 const char *realm, 37 55 struct NETLOGON_SAM_LOGON_RESPONSE_EX *reply5); -
vendor/current/source3/libads/disp_sec.c
r740 r988 30 30 31 31 static struct perm_mask_str { 32 uint32 mask;32 uint32_t mask; 33 33 const char *str; 34 34 } perms[] = { … … 60 60 61 61 /* convert a security permissions into a string */ 62 static void ads_disp_perms(uint32 type)62 static void ads_disp_perms(uint32_t type) 63 63 { 64 64 int i = 0; -
vendor/current/source3/libads/kerberos.c
r860 r988 27 27 #include "../librpc/gen_ndr/ndr_misc.h" 28 28 #include "libads/kerberos_proto.h" 29 #include "libads/cldap.h" 29 30 #include "secrets.h" 31 #include "../lib/tsocket/tsocket.h" 30 32 31 33 #ifdef HAVE_KRB5 32 33 #define DEFAULT_KRB5_PORT 8834 34 35 35 #define LIBADS_CCACHE_NAME "MEMORY:libads" … … 48 48 { 49 49 if (num_prompts == 0) return 0; 50 50 #if HAVE_KRB5_PROMPT_TYPE 51 52 /* 53 * only heimdal has a prompt type and we need to deal with it here to 54 * avoid loops. 55 * 56 * removing the prompter completely is not an option as at least these 57 * versions would crash: heimdal-1.0.2 and heimdal-1.1. Later heimdal 58 * version have looping detection and return with a proper error code. 59 */ 60 61 if ((num_prompts == 2) && 62 (prompts[0].type == KRB5_PROMPT_TYPE_NEW_PASSWORD) && 63 (prompts[1].type == KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN)) { 64 /* 65 * We don't want to change passwords here. We're 66 * called from heimal when the KDC returns 67 * KRB5KDC_ERR_KEY_EXPIRED, but at this point we don't 68 * have the chance to ask the user for a new 69 * password. If we return 0 (i.e. success), we will be 70 * spinning in the endless for-loop in 71 * change_password() in 72 * source4/heimdal/lib/krb5/init_creds_pw.c:526ff 73 */ 74 return KRB5KDC_ERR_KEY_EXPIRED; 75 } 76 #endif /* HAVE_KRB5_PROMPT_TYPE */ 51 77 memset(prompts[0].reply->data, '\0', prompts[0].reply->length); 52 78 if (prompts[0].reply->length > 0) { … … 218 244 #endif 219 245 if (add_netbios_addr) { 220 if ((code = smb_krb5_gen_netbios_krb5_address(&addr))) { 246 if ((code = smb_krb5_gen_netbios_krb5_address(&addr, 247 lp_netbios_name()))) { 221 248 goto out; 222 249 } … … 224 251 } 225 252 226 if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, CONST_DISCARD(char *,password),227 kerb_prompter, CONST_DISCARD(char *,password),253 if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, discard_const_p(char,password), 254 kerb_prompter, discard_const_p(char, password), 228 255 0, NULL, opt))) { 229 256 goto out; … … 353 380 fstring salt; 354 381 355 fstr_sprintf( salt, "host/%s.%s@", global_myname(), lp_realm() );356 strlower_m( salt );382 fstr_sprintf( salt, "host/%s.%s@", lp_netbios_name(), lp_realm() ); 383 (void)strlower_m( salt ); 357 384 fstrcat( salt, lp_realm() ); 358 385 … … 406 433 ************************************************************************/ 407 434 435 static 408 436 char* kerberos_secrets_fetch_des_salt( void ) 409 437 { … … 412 440 if ( (key = des_salt_key()) == NULL ) { 413 441 DEBUG(0,("kerberos_secrets_fetch_des_salt: failed to generate key!\n")); 414 return False;442 return NULL; 415 443 } 416 444 … … 420 448 421 449 return salt; 422 }423 424 /************************************************************************425 Routine to get the default realm from the kerberos credentials cache.426 Caller must free if the return value is not NULL.427 ************************************************************************/428 429 char *kerberos_get_default_realm_from_ccache( void )430 {431 char *realm = NULL;432 krb5_context ctx = NULL;433 krb5_ccache cc = NULL;434 krb5_principal princ = NULL;435 436 initialize_krb5_error_table();437 if (krb5_init_context(&ctx)) {438 return NULL;439 }440 441 DEBUG(5,("kerberos_get_default_realm_from_ccache: "442 "Trying to read krb5 cache: %s\n",443 krb5_cc_default_name(ctx)));444 if (krb5_cc_default(ctx, &cc)) {445 DEBUG(0,("kerberos_get_default_realm_from_ccache: "446 "failed to read default cache\n"));447 goto out;448 }449 if (krb5_cc_get_principal(ctx, cc, &princ)) {450 DEBUG(0,("kerberos_get_default_realm_from_ccache: "451 "failed to get default principal\n"));452 goto out;453 }454 455 #if defined(HAVE_KRB5_PRINCIPAL_GET_REALM)456 realm = SMB_STRDUP(krb5_principal_get_realm(ctx, princ));457 #elif defined(HAVE_KRB5_PRINC_REALM)458 {459 krb5_data *realm_data = krb5_princ_realm(ctx, princ);460 realm = SMB_STRNDUP(realm_data->data, realm_data->length);461 }462 #endif463 464 out:465 466 if (ctx) {467 if (princ) {468 krb5_free_principal(ctx, princ);469 }470 if (cc) {471 krb5_cc_close(ctx, cc);472 }473 krb5_free_context(ctx);474 }475 476 return realm;477 }478 479 /************************************************************************480 Routine to get the realm from a given DNS name. Returns malloc'ed memory.481 Caller must free() if the return value is not NULL.482 ************************************************************************/483 484 char *kerberos_get_realm_from_hostname(const char *hostname)485 {486 #if defined(HAVE_KRB5_GET_HOST_REALM) && defined(HAVE_KRB5_FREE_HOST_REALM)487 #if defined(HAVE_KRB5_REALM_TYPE)488 /* Heimdal. */489 krb5_realm *realm_list = NULL;490 #else491 /* MIT */492 char **realm_list = NULL;493 #endif494 char *realm = NULL;495 krb5_error_code kerr;496 krb5_context ctx = NULL;497 498 initialize_krb5_error_table();499 if (krb5_init_context(&ctx)) {500 return NULL;501 }502 503 kerr = krb5_get_host_realm(ctx, hostname, &realm_list);504 if (kerr != 0) {505 DEBUG(3,("kerberos_get_realm_from_hostname %s: "506 "failed %s\n",507 hostname ? hostname : "(NULL)",508 error_message(kerr) ));509 goto out;510 }511 512 if (realm_list && realm_list[0]) {513 realm = SMB_STRDUP(realm_list[0]);514 }515 516 out:517 518 if (ctx) {519 if (realm_list) {520 krb5_free_host_realm(ctx, realm_list);521 realm_list = NULL;522 }523 krb5_free_context(ctx);524 ctx = NULL;525 }526 return realm;527 #else528 return NULL;529 #endif530 450 } 531 451 … … 537 457 ************************************************************************/ 538 458 459 static 539 460 krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context, 540 461 krb5_principal host_princ, … … 567 488 568 489 return ret_princ; 490 } 491 492 int create_kerberos_key_from_string(krb5_context context, 493 krb5_principal host_princ, 494 krb5_data *password, 495 krb5_keyblock *key, 496 krb5_enctype enctype, 497 bool no_salt) 498 { 499 krb5_principal salt_princ = NULL; 500 int ret; 501 /* 502 * Check if we've determined that the KDC is salting keys for this 503 * principal/enctype in a non-obvious way. If it is, try to match 504 * its behavior. 505 */ 506 if (no_salt) { 507 KRB5_KEY_DATA(key) = (KRB5_KEY_DATA_CAST *)SMB_MALLOC(password->length); 508 if (!KRB5_KEY_DATA(key)) { 509 return ENOMEM; 510 } 511 memcpy(KRB5_KEY_DATA(key), password->data, password->length); 512 KRB5_KEY_LENGTH(key) = password->length; 513 KRB5_KEY_TYPE(key) = enctype; 514 return 0; 515 } 516 salt_princ = kerberos_fetch_salt_princ_for_host_princ(context, host_princ, enctype); 517 ret = smb_krb5_create_key_from_string(context, 518 salt_princ ? salt_princ : host_princ, 519 NULL, 520 password, 521 enctype, 522 key); 523 if (salt_princ) { 524 krb5_free_principal(context, salt_princ); 525 } 526 return ret; 569 527 } 570 528 … … 664 622 ************************************************************************/ 665 623 666 static char *print_kdc_line(char *mem_ctx,667 const char *prev_line,668 const struct sockaddr_storage *pss,669 const char *kdc_name)670 {671 char *kdc_str = NULL;672 673 if (pss->ss_family == AF_INET) {674 kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",675 prev_line,676 print_canonical_sockaddr(mem_ctx, pss));677 } else {678 char addr[INET6_ADDRSTRLEN];679 uint16_t port = get_sockaddr_port(pss);680 681 DEBUG(10,("print_kdc_line: IPv6 case for kdc_name: %s, port: %d\n",682 kdc_name, port));683 684 if (port != 0 && port != DEFAULT_KRB5_PORT) {685 /* Currently for IPv6 we can't specify a non-default686 krb5 port with an address, as this requires a ':'.687 Resolve to a name. */688 char hostname[MAX_DNS_NAME_LENGTH];689 int ret = sys_getnameinfo((const struct sockaddr *)pss,690 sizeof(*pss),691 hostname, sizeof(hostname),692 NULL, 0,693 NI_NAMEREQD);694 if (ret) {695 DEBUG(0,("print_kdc_line: can't resolve name "696 "for kdc with non-default port %s. "697 "Error %s\n.",698 print_canonical_sockaddr(mem_ctx, pss),699 gai_strerror(ret)));700 return NULL;701 }702 /* Success, use host:port */703 kdc_str = talloc_asprintf(mem_ctx,704 "%s\tkdc = %s:%u\n",705 prev_line,706 hostname,707 (unsigned int)port);708 } else {709 710 /* no krb5 lib currently supports "kdc = ipv6 address"711 * at all, so just fill in just the kdc_name if we have712 * it and let the krb5 lib figure out the appropriate713 * ipv6 address - gd */714 715 if (kdc_name) {716 kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",717 prev_line, kdc_name);718 } else {719 kdc_str = talloc_asprintf(mem_ctx, "%s\tkdc = %s\n",720 prev_line,721 print_sockaddr(addr,722 sizeof(addr),723 pss));724 }725 }726 }727 return kdc_str;728 }729 730 624 /************************************************************************ 731 625 Create a string list of available kdc's, possibly searching by sitename. … … 736 630 ************************************************************************/ 737 631 632 static void add_sockaddr_unique(struct sockaddr_storage *addrs, int *num_addrs, 633 const struct sockaddr_storage *addr) 634 { 635 int i; 636 637 for (i=0; i<*num_addrs; i++) { 638 if (sockaddr_equal((const struct sockaddr *)&addrs[i], 639 (const struct sockaddr *)addr)) { 640 return; 641 } 642 } 643 addrs[i] = *addr; 644 *num_addrs += 1; 645 } 646 647 /* print_canonical_sockaddr prints an ipv6 addr in the form of 648 * [ipv6.addr]. This string, when put in a generated krb5.conf file is not 649 * always properly dealt with by some older krb5 libraries. Adding the hard-coded 650 * portnumber workarounds the issue. - gd */ 651 652 static char *print_canonical_sockaddr_with_port(TALLOC_CTX *mem_ctx, 653 const struct sockaddr_storage *pss) 654 { 655 char *str = NULL; 656 657 str = print_canonical_sockaddr(mem_ctx, pss); 658 if (str == NULL) { 659 return NULL; 660 } 661 662 if (pss->ss_family != AF_INET6) { 663 return str; 664 } 665 666 #if defined(HAVE_IPV6) 667 str = talloc_asprintf_append(str, ":88"); 668 #endif 669 return str; 670 } 671 738 672 static char *get_kdc_ip_string(char *mem_ctx, 739 673 const char *realm, 740 674 const char *sitename, 741 struct sockaddr_storage *pss,742 const char *kdc_name) 743 { 675 const struct sockaddr_storage *pss) 676 { 677 TALLOC_CTX *frame = talloc_stackframe(); 744 678 int i; 745 679 struct ip_service *ip_srv_site = NULL; … … 747 681 int count_site = 0; 748 682 int count_nonsite; 749 char *kdc_str = print_kdc_line(mem_ctx, "", pss, kdc_name); 683 int num_dcs; 684 struct sockaddr_storage *dc_addrs; 685 struct tsocket_address **dc_addrs2 = NULL; 686 const struct tsocket_address * const *dc_addrs3 = NULL; 687 char *result = NULL; 688 struct netlogon_samlogon_response **responses = NULL; 689 NTSTATUS status; 690 char *kdc_str = talloc_asprintf(mem_ctx, "%s\t\tkdc = %s\n", "", 691 print_canonical_sockaddr_with_port(mem_ctx, pss)); 750 692 751 693 if (kdc_str == NULL) { 694 TALLOC_FREE(frame); 752 695 return NULL; 753 696 } … … 759 702 760 703 if (sitename) { 761 762 704 get_kdc_list(realm, sitename, &ip_srv_site, &count_site); 763 764 for (i = 0; i < count_site; i++) { 765 if (sockaddr_equal((struct sockaddr *)&ip_srv_site[i].ss, 766 (struct sockaddr *)pss)) { 767 continue; 768 } 769 /* Append to the string - inefficient 770 * but not done often. */ 771 kdc_str = print_kdc_line(mem_ctx, 772 kdc_str, 773 &ip_srv_site[i].ss, 774 NULL); 775 if (!kdc_str) { 776 SAFE_FREE(ip_srv_site); 777 return NULL; 778 } 779 } 705 DEBUG(10, ("got %d addresses from site %s search\n", count_site, 706 sitename)); 780 707 } 781 708 … … 783 710 784 711 get_kdc_list(realm, NULL, &ip_srv_nonsite, &count_nonsite); 712 DEBUG(10, ("got %d addresses from site-less search\n", count_nonsite)); 713 714 dc_addrs = talloc_array(talloc_tos(), struct sockaddr_storage, 715 count_site + count_nonsite); 716 if (dc_addrs == NULL) { 717 goto out; 718 } 719 720 num_dcs = 0; 721 722 for (i = 0; i < count_site; i++) { 723 if (!sockaddr_equal( 724 (const struct sockaddr *)pss, 725 (const struct sockaddr *)&ip_srv_site[i].ss)) { 726 add_sockaddr_unique(dc_addrs, &num_dcs, 727 &ip_srv_site[i].ss); 728 } 729 } 785 730 786 731 for (i = 0; i < count_nonsite; i++) { 787 int j; 788 789 if (sockaddr_equal((struct sockaddr *)&ip_srv_nonsite[i].ss, (struct sockaddr *)pss)) { 732 if (!sockaddr_equal( 733 (const struct sockaddr *)pss, 734 (const struct sockaddr *)&ip_srv_nonsite[i].ss)) { 735 add_sockaddr_unique(dc_addrs, &num_dcs, 736 &ip_srv_nonsite[i].ss); 737 } 738 } 739 740 dc_addrs2 = talloc_zero_array(talloc_tos(), 741 struct tsocket_address *, 742 num_dcs); 743 744 DEBUG(10, ("%d additional KDCs to test\n", num_dcs)); 745 if (num_dcs == 0) { 746 goto out; 747 } 748 if (dc_addrs2 == NULL) { 749 goto out; 750 } 751 752 for (i=0; i<num_dcs; i++) { 753 char addr[INET6_ADDRSTRLEN]; 754 int ret; 755 756 print_sockaddr(addr, sizeof(addr), &dc_addrs[i]); 757 758 ret = tsocket_address_inet_from_strings(dc_addrs2, "ip", 759 addr, LDAP_PORT, 760 &dc_addrs2[i]); 761 if (ret != 0) { 762 status = map_nt_error_from_unix(errno); 763 DEBUG(2,("Failed to create tsocket_address for %s - %s\n", 764 addr, nt_errstr(status))); 765 goto out; 766 } 767 } 768 769 dc_addrs3 = (const struct tsocket_address * const *)dc_addrs2; 770 771 status = cldap_multi_netlogon(talloc_tos(), 772 dc_addrs3, num_dcs, 773 realm, lp_netbios_name(), 774 NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX, 775 MIN(num_dcs, 3), timeval_current_ofs(3, 0), &responses); 776 TALLOC_FREE(dc_addrs2); 777 dc_addrs3 = NULL; 778 779 if (!NT_STATUS_IS_OK(status)) { 780 DEBUG(10,("get_kdc_ip_string: cldap_multi_netlogon failed: " 781 "%s\n", nt_errstr(status))); 782 goto out; 783 } 784 785 for (i=0; i<num_dcs; i++) { 786 char *new_kdc_str; 787 788 if (responses[i] == NULL) { 790 789 continue; 791 790 } 792 791 793 /* Ensure this isn't an IP already seen (YUK! this is n*n....) */794 for (j = 0; j < count_site; j++) {795 if (sockaddr_equal((struct sockaddr *)&ip_srv_nonsite[i].ss,796 (struct sockaddr *)&ip_srv_site[j].ss)) {797 break;798 }799 /* As the lists are sorted we can break early if nonsite > site. */800 if (ip_service_compare(&ip_srv_nonsite[i], &ip_srv_site[j]) > 0) {801 break;802 }803 }804 if (j != i) {805 continue;806 }807 808 792 /* Append to the string - inefficient but not done often. */ 809 kdc_str = print_kdc_line(mem_ctx, 810 kdc_str, 811 &ip_srv_nonsite[i].ss, 812 NULL); 813 if (!kdc_str) { 814 SAFE_FREE(ip_srv_site); 815 SAFE_FREE(ip_srv_nonsite); 816 return NULL; 817 } 818 } 819 820 793 new_kdc_str = talloc_asprintf(mem_ctx, "%s\t\tkdc = %s\n", 794 kdc_str, 795 print_canonical_sockaddr_with_port(mem_ctx, &dc_addrs[i])); 796 if (new_kdc_str == NULL) { 797 goto out; 798 } 799 TALLOC_FREE(kdc_str); 800 kdc_str = new_kdc_str; 801 } 802 803 out: 804 DEBUG(10, ("get_kdc_ip_string: Returning %s\n", kdc_str)); 805 806 result = kdc_str; 821 807 SAFE_FREE(ip_srv_site); 822 808 SAFE_FREE(ip_srv_nonsite); 823 824 DEBUG(10,("get_kdc_ip_string: Returning %s\n", 825 kdc_str )); 826 827 return kdc_str; 809 TALLOC_FREE(frame); 810 return result; 828 811 } 829 812 … … 838 821 const char *domain, 839 822 const char *sitename, 840 struct sockaddr_storage *pss, 841 const char *kdc_name) 823 const struct sockaddr_storage *pss) 842 824 { 843 825 char *dname; … … 852 834 bool result = false; 853 835 char *aes_enctypes = NULL; 836 mode_t mask; 854 837 855 838 if (!lp_create_krb5_conf()) { … … 863 846 } 864 847 865 if (domain == NULL || pss == NULL || kdc_name == NULL) {848 if (domain == NULL || pss == NULL) { 866 849 return false; 867 850 } … … 892 875 893 876 realm_upper = talloc_strdup(fname, realm); 894 strupper_m(realm_upper); 895 896 kdc_ip_string = get_kdc_ip_string(dname, realm, sitename, pss, kdc_name); 877 if (!strupper_m(realm_upper)) { 878 goto done; 879 } 880 881 kdc_ip_string = get_kdc_ip_string(dname, realm, sitename, pss); 897 882 if (!kdc_ip_string) { 898 883 goto done; … … 921 906 "\tdefault_tgs_enctypes = %s RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n" 922 907 "\tdefault_tkt_enctypes = %s RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n" 923 "\tpreferred_enctypes = %s RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n\n" 908 "\tpreferred_enctypes = %s RC4-HMAC DES-CBC-CRC DES-CBC-MD5\n" 909 "\tdns_lookup_realm = false\n\n" 924 910 "[realms]\n\t%s = {\n" 925 " \t%s\t}\n",911 "%s\t}\n", 926 912 realm_upper, aes_enctypes, aes_enctypes, aes_enctypes, 927 913 realm_upper, kdc_ip_string); … … 933 919 flen = strlen(file_contents); 934 920 921 mask = umask(S_IRWXO | S_IRWXG); 935 922 fd = mkstemp(tmpname); 923 umask(mask); 936 924 if (fd == -1) { 937 925 DEBUG(0,("create_local_private_krb5_conf_for_domain: smb_mkstemp failed," … … 989 977 990 978 if (strequal(realm, lp_realm())) { 991 char linkpath[PATH_MAX+1]; 992 int lret; 993 994 lret = readlink(SYSTEM_KRB5_CONF_PATH, linkpath, sizeof(linkpath)-1); 995 if (lret != -1) { 996 linkpath[lret] = '\0'; 997 } 998 999 if (lret != -1 || strcmp(linkpath, fname) == 0) { 1000 /* Symlink already exists. */ 1001 goto done; 979 SMB_STRUCT_STAT sbuf; 980 981 if (sys_lstat(SYSTEM_KRB5_CONF_PATH, &sbuf, false) == 0) { 982 if (S_ISLNK(sbuf.st_ex_mode) && sbuf.st_ex_size) { 983 int lret; 984 size_t alloc_size = sbuf.st_ex_size + 1; 985 char *linkpath = talloc_array(talloc_tos(), char, 986 alloc_size); 987 if (!linkpath) { 988 goto done; 989 } 990 lret = readlink(SYSTEM_KRB5_CONF_PATH, linkpath, 991 alloc_size - 1); 992 if (lret == -1) { 993 TALLOC_FREE(linkpath); 994 goto done; 995 } 996 linkpath[lret] = '\0'; 997 998 if (strcmp(linkpath, fname) == 0) { 999 /* Symlink already exists. */ 1000 TALLOC_FREE(linkpath); 1001 goto done; 1002 } 1003 TALLOC_FREE(linkpath); 1004 } 1002 1005 } 1003 1006 1004 1007 /* Try and replace with a symlink. */ 1005 1008 if (symlink(fname, SYSTEM_KRB5_CONF_PATH) == -1) { 1006 const char *newpath = SYSTEM_KRB5_CONF_PATH ##".saved";1009 const char *newpath = SYSTEM_KRB5_CONF_PATH ".saved"; 1007 1010 if (errno != EEXIST) { 1008 1011 DEBUG(0,("create_local_private_krb5_conf_for_domain: symlink " -
vendor/current/source3/libads/kerberos_keytab.c
r860 r988 50 50 krb5_keytab_entry zero_kt_entry; 51 51 char *ktprinc = NULL; 52 krb5_kvno old_kvno = kvno - 1; 52 53 53 54 ZERO_STRUCT(cursor); … … 116 117 * the client reboots or the client's session key expires and 117 118 * they get a new session ticket with the new kvno. 119 * Some keytab files only store the kvno in 8bits, limit 120 * the compare accordingly. 118 121 */ 119 122 120 if (!flush && ( kt_entry.vno == kvno - 1)) {123 if (!flush && ((kt_entry.vno & 0xff) == (old_kvno & 0xff))) { 121 124 DEBUG(5, (__location__ ": Saving previous (kvno %d) " 122 125 "entry for principal: %s.\n", 123 kvno - 1, princ_s));126 old_kvno, princ_s)); 124 127 continue; 125 128 } … … 250 253 return (int)ret; 251 254 } 255 256 #ifdef HAVE_ADS 252 257 253 258 /********************************************************************** … … 321 326 } 322 327 323 my_fqdn = ads_get_dnshostname(ads, tmpctx, global_myname());328 my_fqdn = ads_get_dnshostname(ads, tmpctx, lp_netbios_name()); 324 329 if (!my_fqdn) { 325 330 DEBUG(0, (__location__ ": unable to determine machine " … … 329 334 } 330 335 331 machine_name = ads_get_samaccountname(ads, tmpctx, global_myname());336 machine_name = ads_get_samaccountname(ads, tmpctx, lp_netbios_name()); 332 337 if (!machine_name) { 333 338 DEBUG(0, (__location__ ": unable to determine machine " … … 369 374 srvPrinc, machine_name, 370 375 lp_realm()); 371 if ( !princ_s) {376 if (short_princ_s == NULL) { 372 377 ret = -1; 373 378 goto out; … … 385 390 386 391 aderr = ads_add_service_principal_name(ads, 387 global_myname(), my_fqdn, srvPrinc);392 lp_netbios_name(), my_fqdn, srvPrinc); 388 393 if (!ADS_ERR_OK(aderr)) { 389 394 DEBUG(1, (__location__ ": failed to " … … 394 399 } 395 400 396 kvno = (krb5_kvno)ads_get_machine_kvno(ads, global_myname());401 kvno = (krb5_kvno)ads_get_machine_kvno(ads, lp_netbios_name()); 397 402 if (kvno == -1) { 398 403 /* -1 indicates failure, everything else is OK */ … … 463 468 } 464 469 465 kvno = (krb5_kvno)ads_get_machine_kvno(ads, global_myname());470 kvno = (krb5_kvno)ads_get_machine_kvno(ads, lp_netbios_name()); 466 471 if (kvno == -1) { 467 472 /* -1 indicates a failure */ … … 477 482 } 478 483 479 aderr = ads_clear_service_principal_names(ads, global_myname());484 aderr = ads_clear_service_principal_names(ads, lp_netbios_name()); 480 485 if (!ADS_ERR_OK(aderr)) { 481 486 DEBUG(1, (__location__ ": Error while clearing service " … … 503 508 krb5_context context = NULL; 504 509 krb5_keytab keytab = NULL; 505 krb5_kt_cursor cursor ;506 krb5_keytab_entry kt_entry ;510 krb5_kt_cursor cursor = {0}; 511 krb5_keytab_entry kt_entry = {0}; 507 512 krb5_kvno kvno; 508 int i,found = 0;513 size_t found = 0; 509 514 char *sam_account_name, *upn; 510 515 char **oldEntries = NULL, *princ_s[26]; 511 TALLOC_CTX * tmpctx = NULL;516 TALLOC_CTX *frame; 512 517 char *machine_name; 513 514 /* these are the main ones we need */ 515 ret = ads_keytab_add_entry(ads, "host"); 516 if (ret != 0) { 517 DEBUG(1, (__location__ ": ads_keytab_add_entry failed while " 518 "adding 'host' principal.\n")); 519 return ret; 520 } 521 518 char **spn_array; 519 size_t num_spns; 520 size_t i; 521 ADS_STATUS status; 522 523 ZERO_STRUCT(kt_entry); 524 ZERO_STRUCT(cursor); 525 526 frame = talloc_stackframe(); 527 if (frame == NULL) { 528 ret = -1; 529 goto done; 530 } 531 532 status = ads_get_service_principal_names(frame, 533 ads, 534 lp_netbios_name(), 535 &spn_array, 536 &num_spns); 537 if (!ADS_ERR_OK(status)) { 538 ret = -1; 539 goto done; 540 } 541 542 for (i = 0; i < num_spns; i++) { 543 char *srv_princ; 544 char *p; 545 546 srv_princ = strlower_talloc(frame, spn_array[i]); 547 if (srv_princ == NULL) { 548 ret = -1; 549 goto done; 550 } 551 552 p = strchr_m(srv_princ, '/'); 553 if (p == NULL) { 554 continue; 555 } 556 p[0] = '\0'; 557 558 /* Add the SPNs found on the DC */ 559 ret = ads_keytab_add_entry(ads, srv_princ); 560 if (ret != 0) { 561 DEBUG(1, ("ads_keytab_add_entry failed while " 562 "adding '%s' principal.\n", 563 spn_array[i])); 564 goto done; 565 } 566 } 522 567 523 568 #if 0 /* don't create the CIFS/... keytab entries since no one except smbd … … 534 579 535 580 memset(princ_s, '\0', sizeof(princ_s)); 536 ZERO_STRUCT(kt_entry);537 ZERO_STRUCT(cursor);538 581 539 582 initialize_krb5_error_table(); … … 542 585 DEBUG(1, (__location__ ": could not krb5_init_context: %s\n", 543 586 error_message(ret))); 544 return ret; 545 } 546 547 tmpctx = talloc_init(__location__); 548 if (!tmpctx) { 549 DEBUG(0, (__location__ ": talloc_init() failed!\n")); 550 ret = -1; 551 goto done; 552 } 553 554 machine_name = talloc_strdup(tmpctx, global_myname()); 587 goto done; 588 } 589 590 machine_name = talloc_strdup(frame, lp_netbios_name()); 555 591 if (!machine_name) { 556 592 ret = -1; … … 559 595 560 596 /* now add the userPrincipalName and sAMAccountName entries */ 561 sam_account_name = ads_get_samaccountname(ads, tmpctx, machine_name);597 sam_account_name = ads_get_samaccountname(ads, frame, machine_name); 562 598 if (!sam_account_name) { 563 599 DEBUG(0, (__location__ ": unable to determine machine " … … 569 605 /* upper case the sAMAccountName to make it easier for apps to 570 606 know what case to use in the keytab file */ 571 strupper_m(sam_account_name); 607 if (!strupper_m(sam_account_name)) { 608 ret = -1; 609 goto done; 610 } 572 611 573 612 ret = ads_keytab_add_entry(ads, sam_account_name); … … 580 619 581 620 /* remember that not every machine account will have a upn */ 582 upn = ads_get_upn(ads, tmpctx, machine_name);621 upn = ads_get_upn(ads, frame, machine_name); 583 622 if (upn) { 584 623 ret = ads_keytab_add_entry(ads, upn); … … 592 631 /* Now loop through the keytab and update any other existing entries */ 593 632 kvno = (krb5_kvno)ads_get_machine_kvno(ads, machine_name); 594 if (kvno == -1) {633 if (kvno == (krb5_kvno)-1) { 595 634 DEBUG(1, (__location__ ": ads_get_machine_kvno() failed to " 596 635 "determine the system's kvno.\n")); … … 625 664 * we've counted them. Re-open asap to minimise the race. JRA. 626 665 */ 627 DEBUG(3, (__location__ ": Found % d entries in the keytab.\n", found));666 DEBUG(3, (__location__ ": Found %zd entries in the keytab.\n", found)); 628 667 if (!found) { 629 668 goto done; 630 669 } 631 670 632 oldEntries = talloc_ array(tmpctx, char *, found);671 oldEntries = talloc_zero_array(frame, char *, found + 1); 633 672 if (!oldEntries) { 634 673 DEBUG(1, (__location__ ": Failed to allocate space to store " … … 637 676 goto done; 638 677 } 639 memset(oldEntries, '\0', found * sizeof(char *));640 678 641 679 ret = krb5_kt_start_seq_get(context, keytab, &cursor); … … 694 732 ZERO_STRUCT(kt_entry); 695 733 } 734 krb5_kt_end_seq_get(context, keytab, &cursor); 735 ZERO_STRUCT(cursor); 736 696 737 ret = 0; 697 738 for (i = 0; oldEntries[i]; i++) { … … 699 740 TALLOC_FREE(oldEntries[i]); 700 741 } 701 krb5_kt_end_seq_get(context, keytab, &cursor);702 ZERO_STRUCT(cursor);703 742 704 743 done: 705 744 TALLOC_FREE(oldEntries); 706 TALLOC_FREE( tmpctx);745 TALLOC_FREE(frame); 707 746 708 747 { … … 730 769 return ret; 731 770 } 771 772 #endif /* HAVE_ADS */ 732 773 733 774 /********************************************************************** … … 767 808 } 768 809 769 printf("Vno Type Principal\n");810 printf("Vno Type Principal\n"); 770 811 771 812 while (krb5_kt_next_entry(context, keytab, &kt_entry, &cursor) == 0) { … … 790 831 } 791 832 792 printf("%3d % s\t\t%s\n", kt_entry.vno, etype_s, princ_s);833 printf("%3d %-43s %s\n", kt_entry.vno, etype_s, princ_s); 793 834 794 835 TALLOC_FREE(princ_s); -
vendor/current/source3/libads/kerberos_proto.h
r740 r988 31 31 #define _LIBADS_KERBEROS_PROTO_H_ 32 32 33 struct PAC_LOGON_INFO; 33 #include "system/kerberos.h" 34 35 struct PAC_DATA; 36 37 struct PAC_DATA_CTR { 38 DATA_BLOB pac_blob; 39 struct PAC_DATA *pac_data; 40 }; 41 42 #define DEFAULT_KRB5_PORT 88 34 43 35 44 #include "libads/ads_status.h" 36 37 /* The following definitions come from libads/kerberos_verify.c */38 39 NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,40 const char *realm,41 time_t time_offset,42 const DATA_BLOB *ticket,43 char **principal,44 struct PAC_LOGON_INFO **logon_info,45 DATA_BLOB *ap_rep,46 DATA_BLOB *session_key,47 bool use_replay_cache);48 45 49 46 /* The following definitions come from libads/kerberos.c */ … … 62 59 char* kerberos_standard_des_salt( void ); 63 60 bool kerberos_secrets_store_des_salt( const char* salt ); 64 char* kerberos_secrets_fetch_des_salt( void );65 char *kerberos_get_default_realm_from_ccache( void );66 char *kerberos_get_realm_from_hostname(const char *hostname);67 61 68 62 bool kerberos_secrets_store_salting_principal(const char *service, … … 76 70 const char *domain, 77 71 const char *sitename, 78 struct sockaddr_storage *pss, 79 const char *kdc_name); 72 const struct sockaddr_storage *pss); 80 73 81 74 /* The following definitions come from libads/authdata.c */ … … 92 85 time_t renewable_time, 93 86 const char *impersonate_princ_s, 94 struct PAC_LOGON_INFO **logon_info); 87 const char *local_service, 88 struct PAC_DATA_CTR **pac_data_ctr); 95 89 96 90 /* The following definitions come from libads/krb5_setpw.c */ … … 103 97 int time_offset); 104 98 99 #ifdef HAVE_KRB5 100 int create_kerberos_key_from_string(krb5_context context, 101 krb5_principal host_princ, 102 krb5_data *password, 103 krb5_keyblock *key, 104 krb5_enctype enctype, 105 bool no_salt); 106 #endif 107 105 108 #endif /* _LIBADS_KERBEROS_PROTO_H_ */ -
vendor/current/source3/libads/kerberos_util.c
r740 r988 22 22 #include "smb_krb5.h" 23 23 #include "ads.h" 24 #include "lib/param/loadparm.h" 24 25 25 26 #ifdef HAVE_KRB5 26 27 /**28 * Set the machine account password29 * @param ads connection to ads server30 * @param hostname machine whose password is being set31 * @param password new password32 * @return status of password change33 **/34 ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads,35 const char *machine_account,36 const char *password)37 {38 ADS_STATUS status;39 char *principal = NULL;40 41 /*42 we need to use the '$' form of the name here (the machine account name),43 as otherwise the server might end up setting the password for a user44 instead45 */46 if (asprintf(&principal, "%s@%s", machine_account, ads->config.realm) < 0) {47 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);48 }49 50 status = ads_krb5_set_password(ads->auth.kdc_server, principal,51 password, ads->auth.time_offset);52 53 SAFE_FREE(principal);54 return status;55 }56 27 57 28 /* run kinit to setup our ccache */ … … 73 44 } else { 74 45 /* always use the sAMAccountName for security = domain */ 75 /* global_myname()$@REA.LM */46 /* lp_netbios_name()$@REA.LM */ 76 47 if ( lp_security() == SEC_DOMAIN ) { 77 fstr_sprintf( acct_name, "%s$", global_myname() );48 fstr_sprintf( acct_name, "%s$", lp_netbios_name() ); 78 49 account_name = acct_name; 79 50 } 80 51 else 81 /* This looks like host/ global_myname()@REA.LM */52 /* This looks like host/lp_netbios_name()@REA.LM */ 82 53 account_name = ads->auth.user_name; 83 54 } … … 93 64 } 94 65 95 ret = kerberos_kinit_password_ext(s, ads->auth.password, ads->auth.time_offset, 96 &ads->auth.tgt_expire, NULL, NULL, False, False, ads->auth.renewable, 97 NULL); 66 ret = kerberos_kinit_password_ext(s, ads->auth.password, 67 ads->auth.time_offset, 68 &ads->auth.tgt_expire, NULL, 69 ads->auth.ccache_name, false, false, 70 ads->auth.renewable, NULL); 98 71 99 72 if (ret) { -
vendor/current/source3/libads/krb5_errs.c
r414 r988 29 29 {KRB5_CC_IO, NT_STATUS_UNEXPECTED_IO_ERROR}, 30 30 {KRB5KDC_ERR_BADOPTION, NT_STATUS_INVALID_PARAMETER}, 31 {KRB5KDC_ERR_CLIENT_REVOKED, NT_STATUS_ACC ESS_DENIED},31 {KRB5KDC_ERR_CLIENT_REVOKED, NT_STATUS_ACCOUNT_LOCKED_OUT}, 32 32 {KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, NT_STATUS_INVALID_ACCOUNT_NAME}, 33 33 {KRB5KDC_ERR_ETYPE_NOSUPP, NT_STATUS_LOGON_FAILURE}, -
vendor/current/source3/libads/krb5_setpw.c
r740 r988 26 26 #ifdef HAVE_KRB5 27 27 28 #define DEFAULT_KPASSWD_PORT 464 29 30 #define KRB5_KPASSWD_VERS_CHANGEPW 1 31 32 #define KRB5_KPASSWD_VERS_SETPW 0xff80 33 #define KRB5_KPASSWD_VERS_SETPW_ALT 2 34 35 #define KRB5_KPASSWD_SUCCESS 0 36 #define KRB5_KPASSWD_MALFORMED 1 37 #define KRB5_KPASSWD_HARDERROR 2 38 #define KRB5_KPASSWD_AUTHERROR 3 39 #define KRB5_KPASSWD_SOFTERROR 4 40 #define KRB5_KPASSWD_ACCESSDENIED 5 41 #define KRB5_KPASSWD_BAD_VERSION 6 42 #define KRB5_KPASSWD_INITIAL_FLAG_NEEDED 7 43 44 /* Those are defined by kerberos-set-passwd-02.txt and are probably 28 /* Those are defined by kerberos-set-passwd-02.txt and are probably 45 29 * not supported by M$ implementation */ 46 30 #define KRB5_KPASSWD_POLICY_REJECT 8 … … 53 37 */ 54 38 55 #define krb5_is_krb_error(packet) \ 56 ( packet && packet->length && (((char *)packet->data)[0] == 0x7e || ((char *)packet->data)[0] == 0x5e)) 57 58 /* This implements kerberos password change protocol as specified in 59 * kerb-chg-password-02.txt and kerberos-set-passwd-02.txt 60 * as well as microsoft version of the protocol 61 * as specified in kerberos-set-passwd-00.txt 62 */ 63 static DATA_BLOB encode_krb5_setpw(const char *principal, const char *password) 64 { 65 char* princ_part1 = NULL; 66 char* princ_part2 = NULL; 67 char* realm = NULL; 68 char* c; 69 char* princ; 70 71 ASN1_DATA *req; 72 DATA_BLOB ret; 73 74 75 princ = SMB_STRDUP(principal); 76 77 if ((c = strchr_m(princ, '/')) == NULL) { 78 c = princ; 79 } else { 80 *c = '\0'; 81 c++; 82 princ_part1 = princ; 83 } 84 85 princ_part2 = c; 86 87 if ((c = strchr_m(c, '@')) != NULL) { 88 *c = '\0'; 89 c++; 90 realm = c; 91 } else { 92 /* We must have a realm component. */ 93 return data_blob_null; 94 } 95 96 req = asn1_init(talloc_tos()); 97 if (req == NULL) { 98 return data_blob_null; 99 } 100 101 asn1_push_tag(req, ASN1_SEQUENCE(0)); 102 asn1_push_tag(req, ASN1_CONTEXT(0)); 103 asn1_write_OctetString(req, password, strlen(password)); 104 asn1_pop_tag(req); 105 106 asn1_push_tag(req, ASN1_CONTEXT(1)); 107 asn1_push_tag(req, ASN1_SEQUENCE(0)); 108 109 asn1_push_tag(req, ASN1_CONTEXT(0)); 110 asn1_write_Integer(req, 1); 111 asn1_pop_tag(req); 112 113 asn1_push_tag(req, ASN1_CONTEXT(1)); 114 asn1_push_tag(req, ASN1_SEQUENCE(0)); 115 116 if (princ_part1) { 117 asn1_write_GeneralString(req, princ_part1); 118 } 119 120 asn1_write_GeneralString(req, princ_part2); 121 asn1_pop_tag(req); 122 asn1_pop_tag(req); 123 asn1_pop_tag(req); 124 asn1_pop_tag(req); 125 126 asn1_push_tag(req, ASN1_CONTEXT(2)); 127 asn1_write_GeneralString(req, realm); 128 asn1_pop_tag(req); 129 asn1_pop_tag(req); 130 131 ret = data_blob(req->data, req->length); 132 asn1_free(req); 133 134 free(princ); 135 136 return ret; 137 } 138 139 static krb5_error_code build_kpasswd_request(uint16 pversion, 140 krb5_context context, 141 krb5_auth_context auth_context, 142 krb5_data *ap_req, 143 const char *princ, 144 const char *passwd, 145 bool use_tcp, 146 krb5_data *packet) 147 { 148 krb5_error_code ret; 149 krb5_data cipherpw; 150 krb5_data encoded_setpw; 151 krb5_replay_data replay; 152 char *p, *msg_start; 153 DATA_BLOB setpw; 154 unsigned int msg_length; 155 156 ret = krb5_auth_con_setflags(context, 157 auth_context,KRB5_AUTH_CONTEXT_DO_SEQUENCE); 158 if (ret) { 159 DEBUG(1,("krb5_auth_con_setflags failed (%s)\n", 160 error_message(ret))); 161 return ret; 162 } 163 164 /* handle protocol differences in chpw and setpw */ 165 if (pversion == KRB5_KPASSWD_VERS_CHANGEPW) 166 setpw = data_blob(passwd, strlen(passwd)); 167 else if (pversion == KRB5_KPASSWD_VERS_SETPW || 168 pversion == KRB5_KPASSWD_VERS_SETPW_ALT) 169 setpw = encode_krb5_setpw(princ, passwd); 170 else 171 return EINVAL; 172 173 if (setpw.data == NULL || setpw.length == 0) { 174 return EINVAL; 175 } 176 177 encoded_setpw.data = (char *)setpw.data; 178 encoded_setpw.length = setpw.length; 179 180 ret = krb5_mk_priv(context, auth_context, 181 &encoded_setpw, &cipherpw, &replay); 182 183 data_blob_free(&setpw); /*from 'encode_krb5_setpw(...)' */ 184 185 if (ret) { 186 DEBUG(1,("krb5_mk_priv failed (%s)\n", error_message(ret))); 187 return ret; 188 } 189 190 packet->data = (char *)SMB_MALLOC(ap_req->length + cipherpw.length + (use_tcp ? 10 : 6 )); 191 if (!packet->data) 192 return -1; 193 194 195 196 /* see the RFC for details */ 197 198 msg_start = p = ((char *)packet->data) + (use_tcp ? 4 : 0); 199 p += 2; 200 RSSVAL(p, 0, pversion); 201 p += 2; 202 RSSVAL(p, 0, ap_req->length); 203 p += 2; 204 memcpy(p, ap_req->data, ap_req->length); 205 p += ap_req->length; 206 memcpy(p, cipherpw.data, cipherpw.length); 207 p += cipherpw.length; 208 packet->length = PTR_DIFF(p,packet->data); 209 msg_length = PTR_DIFF(p,msg_start); 210 211 if (use_tcp) { 212 RSIVAL(packet->data, 0, msg_length); 213 } 214 RSSVAL(msg_start, 0, msg_length); 215 216 free(cipherpw.data); /* from 'krb5_mk_priv(...)' */ 217 218 return 0; 219 } 220 221 static const struct kpasswd_errors { 222 int result_code; 223 const char *error_string; 224 } kpasswd_errors[] = { 225 {KRB5_KPASSWD_MALFORMED, "Malformed request error"}, 226 {KRB5_KPASSWD_HARDERROR, "Server error"}, 227 {KRB5_KPASSWD_AUTHERROR, "Authentication error"}, 228 {KRB5_KPASSWD_SOFTERROR, "Password change rejected"}, 229 {KRB5_KPASSWD_ACCESSDENIED, "Client does not have proper authorization"}, 230 {KRB5_KPASSWD_BAD_VERSION, "Protocol version not supported"}, 231 {KRB5_KPASSWD_INITIAL_FLAG_NEEDED, "Authorization ticket must have initial flag set"}, 232 {KRB5_KPASSWD_POLICY_REJECT, "Password rejected due to policy requirements"}, 233 {KRB5_KPASSWD_BAD_PRINCIPAL, "Target principal does not exist"}, 234 {KRB5_KPASSWD_ETYPE_NOSUPP, "Unsupported encryption type"}, 235 {0, NULL} 236 }; 237 238 static krb5_error_code setpw_result_code_string(krb5_context context, 239 int result_code, 240 const char **code_string) 241 { 242 unsigned int idx = 0; 243 244 while (kpasswd_errors[idx].error_string != NULL) { 245 if (kpasswd_errors[idx].result_code == 246 result_code) { 247 *code_string = kpasswd_errors[idx].error_string; 248 return 0; 249 } 250 idx++; 251 } 252 *code_string = "Password change failed"; 253 return (0); 254 } 255 256 krb5_error_code kpasswd_err_to_krb5_err(krb5_error_code res_code) 39 static krb5_error_code kpasswd_err_to_krb5_err(krb5_error_code res_code) 257 40 { 258 41 switch(res_code) { … … 273 56 } 274 57 } 275 static krb5_error_code parse_setpw_reply(krb5_context context, 276 bool use_tcp, 277 krb5_auth_context auth_context, 278 krb5_data *packet) 279 { 280 krb5_data ap_rep; 281 char *p; 282 int vnum, ret, res_code; 283 krb5_data cipherresult; 284 krb5_data clearresult; 285 krb5_ap_rep_enc_part *ap_rep_enc; 286 krb5_replay_data replay; 287 unsigned int msg_length = packet->length; 288 289 290 if (packet->length < (use_tcp ? 8 : 4)) { 291 return KRB5KRB_AP_ERR_MODIFIED; 292 } 293 294 p = (char *)packet->data; 295 /* 296 ** see if it is an error 297 */ 298 if (krb5_is_krb_error(packet)) { 299 300 ret = handle_krberror_packet(context, packet); 301 if (ret) { 302 return ret; 303 } 304 } 305 306 307 /* tcp... */ 308 if (use_tcp) { 309 msg_length -= 4; 310 if (RIVAL(p, 0) != msg_length) { 311 DEBUG(1,("Bad TCP packet length (%d/%d) from kpasswd server\n", 312 RIVAL(p, 0), msg_length)); 313 return KRB5KRB_AP_ERR_MODIFIED; 314 } 315 316 p += 4; 317 } 318 319 if (RSVAL(p, 0) != msg_length) { 320 DEBUG(1,("Bad packet length (%d/%d) from kpasswd server\n", 321 RSVAL(p, 0), msg_length)); 322 return KRB5KRB_AP_ERR_MODIFIED; 323 } 324 325 p += 2; 326 327 vnum = RSVAL(p, 0); p += 2; 328 329 /* FIXME: According to standard there is only one type of reply */ 330 if (vnum != KRB5_KPASSWD_VERS_SETPW && 331 vnum != KRB5_KPASSWD_VERS_SETPW_ALT && 332 vnum != KRB5_KPASSWD_VERS_CHANGEPW) { 333 DEBUG(1,("Bad vnum (%d) from kpasswd server\n", vnum)); 334 return KRB5KDC_ERR_BAD_PVNO; 335 } 336 337 ap_rep.length = RSVAL(p, 0); p += 2; 338 339 if (p + ap_rep.length >= (char *)packet->data + packet->length) { 340 DEBUG(1,("ptr beyond end of packet from kpasswd server\n")); 341 return KRB5KRB_AP_ERR_MODIFIED; 342 } 343 344 if (ap_rep.length == 0) { 345 DEBUG(1,("got unencrypted setpw result?!\n")); 346 return KRB5KRB_AP_ERR_MODIFIED; 347 } 348 349 /* verify ap_rep */ 350 ap_rep.data = p; 351 p += ap_rep.length; 352 353 ret = krb5_rd_rep(context, auth_context, &ap_rep, &ap_rep_enc); 354 if (ret) { 355 DEBUG(1,("failed to rd setpw reply (%s)\n", error_message(ret))); 356 return KRB5KRB_AP_ERR_MODIFIED; 357 } 358 359 krb5_free_ap_rep_enc_part(context, ap_rep_enc); 360 361 cipherresult.data = p; 362 cipherresult.length = ((char *)packet->data + packet->length) - p; 363 364 ret = krb5_rd_priv(context, auth_context, &cipherresult, &clearresult, 365 &replay); 366 if (ret) { 367 DEBUG(1,("failed to decrypt setpw reply (%s)\n", error_message(ret))); 368 return KRB5KRB_AP_ERR_MODIFIED; 369 } 370 371 if (clearresult.length < 2) { 372 free(clearresult.data); 373 ret = KRB5KRB_AP_ERR_MODIFIED; 374 return KRB5KRB_AP_ERR_MODIFIED; 375 } 376 377 p = (char *)clearresult.data; 378 379 res_code = RSVAL(p, 0); 380 381 free(clearresult.data); 382 383 if ((res_code < KRB5_KPASSWD_SUCCESS) || 384 (res_code > KRB5_KPASSWD_ETYPE_NOSUPP)) { 385 return KRB5KRB_AP_ERR_MODIFIED; 386 } 387 388 if (res_code == KRB5_KPASSWD_SUCCESS) { 389 return 0; 390 } else { 391 const char *errstr; 392 setpw_result_code_string(context, res_code, &errstr); 393 DEBUG(1, ("Error changing password: %s (%d)\n", errstr, res_code)); 394 395 return kpasswd_err_to_krb5_err(res_code); 396 } 397 } 398 399 static ADS_STATUS do_krb5_kpasswd_request(krb5_context context, 400 const char *kdc_host, 401 uint16 pversion, 402 krb5_creds *credsp, 403 const char *princ, 404 const char *newpw) 405 { 406 krb5_auth_context auth_context = NULL; 407 krb5_data ap_req, chpw_req, chpw_rep; 408 int ret, sock; 409 socklen_t addr_len; 410 struct sockaddr_storage remote_addr, local_addr; 411 struct sockaddr_storage addr; 412 krb5_address local_kaddr, remote_kaddr; 413 bool use_tcp = False; 414 415 416 if (!interpret_string_addr(&addr, kdc_host, 0)) { 417 } 418 419 ret = krb5_mk_req_extended(context, &auth_context, AP_OPTS_USE_SUBKEY, 420 NULL, credsp, &ap_req); 421 if (ret) { 422 DEBUG(1,("krb5_mk_req_extended failed (%s)\n", error_message(ret))); 423 return ADS_ERROR_KRB5(ret); 424 } 425 426 do { 427 428 if (!use_tcp) { 429 430 sock = open_udp_socket(kdc_host, DEFAULT_KPASSWD_PORT); 431 if (sock == -1) { 432 int rc = errno; 433 SAFE_FREE(ap_req.data); 434 krb5_auth_con_free(context, auth_context); 435 DEBUG(1,("failed to open kpasswd socket to %s " 436 "(%s)\n", kdc_host, strerror(errno))); 437 return ADS_ERROR_SYSTEM(rc); 438 } 439 } else { 440 NTSTATUS status; 441 status = open_socket_out(&addr, DEFAULT_KPASSWD_PORT, 442 LONG_CONNECT_TIMEOUT, &sock); 443 if (!NT_STATUS_IS_OK(status)) { 444 SAFE_FREE(ap_req.data); 445 krb5_auth_con_free(context, auth_context); 446 DEBUG(1,("failed to open kpasswd socket to %s " 447 "(%s)\n", kdc_host, 448 nt_errstr(status))); 449 return ADS_ERROR_NT(status); 450 } 451 } 452 453 addr_len = sizeof(remote_addr); 454 if (getpeername(sock, (struct sockaddr *)&remote_addr, &addr_len) != 0) { 455 close(sock); 456 SAFE_FREE(ap_req.data); 457 krb5_auth_con_free(context, auth_context); 458 DEBUG(1,("getpeername() failed (%s)\n", error_message(errno))); 459 return ADS_ERROR_SYSTEM(errno); 460 } 461 addr_len = sizeof(local_addr); 462 if (getsockname(sock, (struct sockaddr *)&local_addr, &addr_len) != 0) { 463 close(sock); 464 SAFE_FREE(ap_req.data); 465 krb5_auth_con_free(context, auth_context); 466 DEBUG(1,("getsockname() failed (%s)\n", error_message(errno))); 467 return ADS_ERROR_SYSTEM(errno); 468 } 469 if (!setup_kaddr(&remote_kaddr, &remote_addr) || 470 !setup_kaddr(&local_kaddr, &local_addr)) { 471 DEBUG(1,("do_krb5_kpasswd_request: " 472 "Failed to setup addresses.\n")); 473 close(sock); 474 SAFE_FREE(ap_req.data); 475 krb5_auth_con_free(context, auth_context); 476 errno = EINVAL; 477 return ADS_ERROR_SYSTEM(EINVAL); 478 } 479 480 ret = krb5_auth_con_setaddrs(context, auth_context, &local_kaddr, NULL); 481 if (ret) { 482 close(sock); 483 SAFE_FREE(ap_req.data); 484 krb5_auth_con_free(context, auth_context); 485 DEBUG(1,("krb5_auth_con_setaddrs failed (%s)\n", error_message(ret))); 486 return ADS_ERROR_KRB5(ret); 487 } 488 489 ret = build_kpasswd_request(pversion, context, auth_context, &ap_req, 490 princ, newpw, use_tcp, &chpw_req); 491 if (ret) { 492 close(sock); 493 SAFE_FREE(ap_req.data); 494 krb5_auth_con_free(context, auth_context); 495 DEBUG(1,("build_setpw_request failed (%s)\n", error_message(ret))); 496 return ADS_ERROR_KRB5(ret); 497 } 498 499 ret = write(sock, chpw_req.data, chpw_req.length); 500 501 if (ret != chpw_req.length) { 502 close(sock); 503 SAFE_FREE(chpw_req.data); 504 SAFE_FREE(ap_req.data); 505 krb5_auth_con_free(context, auth_context); 506 DEBUG(1,("send of chpw failed (%s)\n", strerror(errno))); 507 return ADS_ERROR_SYSTEM(errno); 508 } 509 510 SAFE_FREE(chpw_req.data); 511 512 chpw_rep.length = 1500; 513 chpw_rep.data = (char *) SMB_MALLOC(chpw_rep.length); 514 if (!chpw_rep.data) { 515 close(sock); 516 SAFE_FREE(ap_req.data); 517 krb5_auth_con_free(context, auth_context); 518 DEBUG(1,("send of chpw failed (%s)\n", strerror(errno))); 519 errno = ENOMEM; 520 return ADS_ERROR_SYSTEM(errno); 521 } 522 523 ret = read(sock, chpw_rep.data, chpw_rep.length); 524 if (ret < 0) { 525 close(sock); 526 SAFE_FREE(chpw_rep.data); 527 SAFE_FREE(ap_req.data); 528 krb5_auth_con_free(context, auth_context); 529 DEBUG(1,("recv of chpw reply failed (%s)\n", strerror(errno))); 530 return ADS_ERROR_SYSTEM(errno); 531 } 532 533 close(sock); 534 chpw_rep.length = ret; 535 536 ret = krb5_auth_con_setaddrs(context, auth_context, NULL,&remote_kaddr); 537 if (ret) { 538 SAFE_FREE(chpw_rep.data); 539 SAFE_FREE(ap_req.data); 540 krb5_auth_con_free(context, auth_context); 541 DEBUG(1,("krb5_auth_con_setaddrs on reply failed (%s)\n", 542 error_message(ret))); 543 return ADS_ERROR_KRB5(ret); 544 } 545 546 ret = parse_setpw_reply(context, use_tcp, auth_context, &chpw_rep); 547 SAFE_FREE(chpw_rep.data); 548 549 if (ret) { 550 551 if (ret == KRB5KRB_ERR_RESPONSE_TOO_BIG && !use_tcp) { 552 DEBUG(5, ("Trying setpw with TCP!!!\n")); 553 use_tcp = True; 554 continue; 555 } 556 557 SAFE_FREE(ap_req.data); 558 krb5_auth_con_free(context, auth_context); 559 DEBUG(1,("parse_setpw_reply failed (%s)\n", 560 error_message(ret))); 561 return ADS_ERROR_KRB5(ret); 562 } 563 564 SAFE_FREE(ap_req.data); 565 krb5_auth_con_free(context, auth_context); 566 } while ( ret ); 567 568 return ADS_SUCCESS; 569 } 570 571 ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *princ, 58 59 ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *principal, 572 60 const char *newpw, int time_offset) 573 61 { … … 576 64 krb5_error_code ret = 0; 577 65 krb5_context context = NULL; 578 const char *realm = NULL; 579 unsigned int realm_len = 0; 580 krb5_creds creds, *credsp = NULL; 66 krb5_principal princ = NULL; 581 67 krb5_ccache ccache = NULL; 582 583 ZERO_STRUCT(creds); 584 68 int result_code; 69 krb5_data result_code_string = { 0 }; 70 krb5_data result_string = { 0 }; 71 585 72 initialize_krb5_error_table(); 586 73 ret = krb5_init_context(&context); … … 589 76 return ADS_ERROR_KRB5(ret); 590 77 } 591 78 79 if (principal) { 80 ret = smb_krb5_parse_name(context, principal, &princ); 81 if (ret) { 82 krb5_free_context(context); 83 DEBUG(1, ("Failed to parse %s (%s)\n", principal, 84 error_message(ret))); 85 return ADS_ERROR_KRB5(ret); 86 } 87 } 88 592 89 if (time_offset != 0) { 593 90 krb5_set_real_time(context, time(NULL) + time_offset, 0); … … 596 93 ret = krb5_cc_default(context, &ccache); 597 94 if (ret) { 95 krb5_free_principal(context, princ); 598 96 krb5_free_context(context); 599 97 DEBUG(1,("Failed to get default creds (%s)\n", error_message(ret))); … … 601 99 } 602 100 603 ret = krb5_cc_get_principal(context, ccache, &creds.client); 101 ret = krb5_set_password_using_ccache(context, 102 ccache, 103 discard_const_p(char, newpw), 104 princ, 105 &result_code, 106 &result_code_string, 107 &result_string); 604 108 if (ret) { 605 krb5_cc_close(context, ccache); 606 krb5_free_context(context); 607 DEBUG(1,("Failed to get principal from ccache (%s)\n", 608 error_message(ret))); 609 return ADS_ERROR_KRB5(ret); 610 } 611 612 realm = smb_krb5_principal_get_realm(context, creds.client); 613 realm_len = strlen(realm); 614 ret = krb5_build_principal(context, 615 &creds.server, 616 realm_len, 617 realm, "kadmin", "changepw", NULL); 618 619 ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp); 620 if (ret) { 621 krb5_cc_close(context, ccache); 622 krb5_free_principal(context, creds.client); 623 krb5_free_principal(context, creds.server); 624 krb5_free_context(context); 625 DEBUG(1,("krb5_build_prinipal_ext (%s)\n", error_message(ret))); 626 return ADS_ERROR_KRB5(ret); 627 } 628 629 ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp); 630 if (ret) { 631 krb5_cc_close(context, ccache); 632 krb5_free_principal(context, creds.client); 633 krb5_free_principal(context, creds.server); 634 krb5_free_context(context); 635 DEBUG(1,("krb5_get_credentials failed (%s)\n", error_message(ret))); 636 return ADS_ERROR_KRB5(ret); 637 } 638 639 /* we might have to call krb5_free_creds(...) from now on ... */ 640 641 aret = do_krb5_kpasswd_request(context, kdc_host, 642 KRB5_KPASSWD_VERS_SETPW, 643 credsp, princ, newpw); 644 645 krb5_free_creds(context, credsp); 646 krb5_free_principal(context, creds.client); 647 krb5_free_principal(context, creds.server); 109 DEBUG(1, ("krb5_set_password failed (%s)\n", error_message(ret))); 110 aret = ADS_ERROR_KRB5(ret); 111 goto done; 112 } 113 114 if (result_code != KRB5_KPASSWD_SUCCESS) { 115 ret = kpasswd_err_to_krb5_err(result_code); 116 DEBUG(1, ("krb5_set_password failed (%s)\n", error_message(ret))); 117 aret = ADS_ERROR_KRB5(ret); 118 goto done; 119 } 120 121 aret = ADS_SUCCESS; 122 123 done: 124 kerberos_free_data_contents(context, &result_code_string); 125 kerberos_free_data_contents(context, &result_string); 126 krb5_free_principal(context, princ); 648 127 krb5_cc_close(context, ccache); 649 128 krb5_free_context(context); … … 693 172 krb5_creds creds; 694 173 char *chpw_princ = NULL, *password; 695 const char *realm = NULL; 174 char *realm = NULL; 175 int result_code; 176 krb5_data result_code_string = { 0 }; 177 krb5_data result_string = { 0 }; 178 smb_krb5_addresses *addr = NULL; 696 179 697 180 initialize_krb5_error_table(); … … 710 193 711 194 krb5_get_init_creds_opt_init(&opts); 195 712 196 krb5_get_init_creds_opt_set_tkt_life(&opts, 5*60); 713 197 krb5_get_init_creds_opt_set_renew_life(&opts, 0); … … 715 199 krb5_get_init_creds_opt_set_proxiable(&opts, 0); 716 200 201 /* note that heimdal will fill in the local addresses if the addresses 202 * in the creds_init_opt are all empty and then later fail with invalid 203 * address, sending our local netbios krb5 address - just like windows 204 * - avoids this - gd */ 205 ret = smb_krb5_gen_netbios_krb5_address(&addr, lp_netbios_name()); 206 if (ret) { 207 krb5_free_principal(context, princ); 208 krb5_free_context(context); 209 return ADS_ERROR_KRB5(ret); 210 } 211 krb5_get_init_creds_opt_set_address_list(&opts, addr->addrs); 212 717 213 realm = smb_krb5_principal_get_realm(context, princ); 718 214 … … 720 216 if (asprintf(&chpw_princ, "kadmin/changepw@%s", realm) == -1) { 721 217 krb5_free_context(context); 218 free(realm); 722 219 DEBUG(1,("ads_krb5_chg_password: asprintf fail\n")); 723 220 return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); 724 221 } 725 222 223 free(realm); 726 224 password = SMB_STRDUP(oldpw); 727 225 ret = krb5_get_init_creds_password(context, &creds, princ, password, … … 742 240 } 743 241 744 aret = do_krb5_kpasswd_request(context, kdc_host, 745 KRB5_KPASSWD_VERS_CHANGEPW, 746 &creds, principal, newpw); 747 242 ret = krb5_change_password(context, 243 &creds, 244 discard_const_p(char, newpw), 245 &result_code, 246 &result_code_string, 247 &result_string); 248 if (ret) { 249 DEBUG(1, ("krb5_change_password failed (%s)\n", error_message(ret))); 250 aret = ADS_ERROR_KRB5(ret); 251 goto done; 252 } 253 254 if (result_code != KRB5_KPASSWD_SUCCESS) { 255 ret = kpasswd_err_to_krb5_err(result_code); 256 DEBUG(1, ("krb5_change_password failed (%s)\n", error_message(ret))); 257 aret = ADS_ERROR_KRB5(ret); 258 goto done; 259 } 260 261 aret = ADS_SUCCESS; 262 263 done: 264 kerberos_free_data_contents(context, &result_code_string); 265 kerberos_free_data_contents(context, &result_string); 748 266 krb5_free_principal(context, princ); 749 267 krb5_free_context(context); -
vendor/current/source3/libads/ldap.c
r860 r988 26 26 #include "libads/sitename_cache.h" 27 27 #include "libads/cldap.h" 28 #include " libads/dns.h"28 #include "../lib/addns/dnsquery.h" 29 29 #include "../libds/common/flags.h" 30 30 #include "smbldap.h" 31 31 #include "../libcli/security/security.h" 32 #include "../librpc/gen_ndr/netlogon.h" 33 #include "lib/param/loadparm.h" 32 34 33 35 #ifdef HAVE_LDAP … … 60 62 } 61 63 62 LDAP *ldap_open_with_timeout(const char *server, int port, unsigned int to) 64 LDAP *ldap_open_with_timeout(const char *server, 65 struct sockaddr_storage *ss, 66 int port, unsigned int to) 63 67 { 64 68 LDAP *ldp = NULL; 65 69 int ldap_err; 70 char *uri; 66 71 67 72 DEBUG(10, ("Opening connection to LDAP server '%s:%d', timeout " 68 73 "%u seconds\n", server, port, to)); 69 74 70 /* Setup timeout */ 71 gotalarm = 0; 72 CatchSignal(SIGALRM, gotalarm_sig); 73 alarm(to); 74 /* End setup timeout. */ 75 75 if (to) { 76 /* Setup timeout */ 77 gotalarm = 0; 78 CatchSignal(SIGALRM, gotalarm_sig); 79 alarm(to); 80 /* End setup timeout. */ 81 } 82 83 if ( strchr_m(server, ':') ) { 84 /* IPv6 URI */ 85 uri = talloc_asprintf(talloc_tos(), "ldap://[%s]:%u", server, port); 86 } else { 87 /* IPv4 URI */ 88 uri = talloc_asprintf(talloc_tos(), "ldap://%s:%u", server, port); 89 } 90 if (uri == NULL) { 91 return NULL; 92 } 93 94 #ifdef HAVE_LDAP_INITIALIZE 95 ldap_err = ldap_initialize(&ldp, uri); 96 #else 76 97 ldp = ldap_open(server, port); 77 78 if (ldp == NULL) { 79 DEBUG(2,("Could not open connection to LDAP server %s:%d: %s\n", 80 server, port, strerror(errno))); 98 if (ldp != NULL) { 99 ldap_err = LDAP_SUCCESS; 81 100 } else { 82 DEBUG(10, ("Connected to LDAP server '%s:%d'\n", server, port)); 83 } 84 85 /* Teardown timeout. */ 86 CatchSignal(SIGALRM, SIG_IGN); 87 alarm(0); 101 ldap_err = LDAP_OTHER; 102 } 103 #endif 104 if (ldap_err != LDAP_SUCCESS) { 105 DEBUG(2,("Could not initialize connection for LDAP server '%s': %s\n", 106 uri, ldap_err2string(ldap_err))); 107 } else { 108 DEBUG(10, ("Initialized connection for LDAP server '%s'\n", uri)); 109 } 110 111 if (to) { 112 /* Teardown timeout. */ 113 alarm(0); 114 CatchSignal(SIGALRM, SIG_IGN); 115 } 88 116 89 117 return ldp; … … 101 129 LDAPMessage **res ) 102 130 { 131 int to = lp_ldap_timeout(); 103 132 struct timeval timeout; 133 struct timeval *timeout_ptr = NULL; 104 134 int result; 105 135 106 136 /* Setup timeout for the ldap_search_ext_s call - local and remote. */ 107 timeout.tv_sec = lp_ldap_timeout();108 timeout.tv_usec = 0;109 110 /* Setup alarm timeout.... Do we need both of these ? JRA. */111 137 gotalarm = 0; 112 CatchSignal(SIGALRM, gotalarm_sig); 113 alarm(lp_ldap_timeout()); 114 /* End setup timeout. */ 138 139 if (to) { 140 timeout.tv_sec = to; 141 timeout.tv_usec = 0; 142 timeout_ptr = &timeout; 143 144 /* Setup alarm timeout. */ 145 CatchSignal(SIGALRM, gotalarm_sig); 146 /* Make the alarm time one second beyond 147 the timout we're setting for the 148 remote search timeout, to allow that 149 to fire in preference. */ 150 alarm(to+1); 151 /* End setup timeout. */ 152 } 153 115 154 116 155 result = ldap_search_ext_s(ld, base, scope, filter, attrs, 117 attrsonly, sctrls, cctrls, &timeout,156 attrsonly, sctrls, cctrls, timeout_ptr, 118 157 sizelimit, res); 119 158 120 /* Teardown timeout. */ 121 CatchSignal(SIGALRM, SIG_IGN); 122 alarm(0); 159 if (to) { 160 /* Teardown alarm timeout. */ 161 CatchSignal(SIGALRM, SIG_IGN); 162 alarm(0); 163 } 123 164 124 165 if (gotalarm != 0) … … 195 236 in the ads struct if successful 196 237 */ 197 static bool ads_try_connect(ADS_STRUCT *ads, const char *server, bool gc)198 { 199 char *srv; 238 static bool ads_try_connect(ADS_STRUCT *ads, bool gc, 239 struct sockaddr_storage *ss) 240 { 200 241 struct NETLOGON_SAM_LOGON_RESPONSE_EX cldap_reply; 201 242 TALLOC_CTX *frame = talloc_stackframe(); 202 243 bool ret = false; 203 204 if (!server || !*server) { 244 char addr[INET6_ADDRSTRLEN]; 245 246 if (ss == NULL) { 205 247 TALLOC_FREE(frame); 206 248 return False; 207 249 } 208 250 209 if (!is_ipaddress(server)) { 210 struct sockaddr_storage ss; 211 char addr[INET6_ADDRSTRLEN]; 212 213 if (!resolve_name(server, &ss, 0x20, true)) { 214 DEBUG(5,("ads_try_connect: unable to resolve name %s\n", 215 server )); 216 TALLOC_FREE(frame); 217 return false; 218 } 219 print_sockaddr(addr, sizeof(addr), &ss); 220 srv = talloc_strdup(frame, addr); 221 } else { 222 /* this copes with inet_ntoa brokenness */ 223 srv = talloc_strdup(frame, server); 224 } 225 226 if (!srv) { 227 TALLOC_FREE(frame); 228 return false; 229 } 251 print_sockaddr(addr, sizeof(addr), ss); 230 252 231 253 DEBUG(5,("ads_try_connect: sending CLDAP request to %s (realm: %s)\n", 232 srv, ads->server.realm));254 addr, ads->server.realm)); 233 255 234 256 ZERO_STRUCT( cldap_reply ); 235 257 236 if ( !ads_cldap_netlogon_5(frame, s rv, ads->server.realm, &cldap_reply ) ) {237 DEBUG(3,("ads_try_connect: CLDAP request %s failed.\n", srv));258 if ( !ads_cldap_netlogon_5(frame, ss, ads->server.realm, &cldap_reply ) ) { 259 DEBUG(3,("ads_try_connect: CLDAP request %s failed.\n", addr)); 238 260 ret = false; 239 261 goto out; … … 244 266 if ( !(cldap_reply.server_type & NBT_SERVER_LDAP) ) { 245 267 DEBUG(1,("ads_try_connect: %s's CLDAP reply says it is not an LDAP server!\n", 246 srv));268 addr)); 247 269 ret = false; 248 270 goto out; … … 261 283 ads->config.ldap_server_name = SMB_STRDUP(cldap_reply.pdc_dns_name); 262 284 ads->config.realm = SMB_STRDUP(cldap_reply.dns_domain); 263 strupper_m(ads->config.realm); 285 if (!strupper_m(ads->config.realm)) { 286 ret = false; 287 goto out; 288 } 289 264 290 ads->config.bind_path = ads_build_dn(ads->config.realm); 265 291 if (*cldap_reply.server_site) { … … 274 300 275 301 ads->ldap.port = gc ? LDAP_GC_PORT : LDAP_PORT; 276 if (!interpret_string_addr(&ads->ldap.ss, srv, 0)) { 277 DEBUG(1,("ads_try_connect: unable to convert %s " 278 "to an address\n", 279 srv)); 280 ret = false; 281 goto out; 282 } 302 ads->ldap.ss = *ss; 283 303 284 304 /* Store our site name. */ … … 295 315 296 316 /********************************************************************** 317 send a cldap ping to list of servers, one at a time, until one of 318 them answers it's an ldap server. Record success in the ADS_STRUCT. 319 Take note of and update negative connection cache. 320 **********************************************************************/ 321 322 static NTSTATUS cldap_ping_list(ADS_STRUCT *ads,const char *domain, 323 struct ip_service *ip_list, int count) 324 { 325 int i; 326 bool ok; 327 328 for (i = 0; i < count; i++) { 329 char server[INET6_ADDRSTRLEN]; 330 331 print_sockaddr(server, sizeof(server), &ip_list[i].ss); 332 333 if (!NT_STATUS_IS_OK( 334 check_negative_conn_cache(domain, server))) 335 continue; 336 337 ok = ads_try_connect(ads, false, &ip_list[i].ss); 338 if (ok) { 339 return NT_STATUS_OK; 340 } 341 342 /* keep track of failures */ 343 add_failed_connection_entry(domain, server, 344 NT_STATUS_UNSUCCESSFUL); 345 } 346 347 return NT_STATUS_NO_LOGON_SERVERS; 348 } 349 350 /*************************************************************************** 351 resolve a name and perform an "ldap ping" using NetBIOS and related methods 352 ****************************************************************************/ 353 354 static NTSTATUS resolve_and_ping_netbios(ADS_STRUCT *ads, 355 const char *domain, const char *realm) 356 { 357 int count, i; 358 struct ip_service *ip_list; 359 NTSTATUS status = NT_STATUS_UNSUCCESSFUL; 360 361 DEBUG(6, ("resolve_and_ping_netbios: (cldap) looking for domain '%s'\n", 362 domain)); 363 364 status = get_sorted_dc_list(domain, NULL, &ip_list, &count, 365 false); 366 if (!NT_STATUS_IS_OK(status)) { 367 return status; 368 } 369 370 /* remove servers which are known to be dead based on 371 the corresponding DNS method */ 372 if (*realm) { 373 for (i = 0; i < count; ++i) { 374 char server[INET6_ADDRSTRLEN]; 375 376 print_sockaddr(server, sizeof(server), &ip_list[i].ss); 377 378 if(!NT_STATUS_IS_OK( 379 check_negative_conn_cache(realm, server))) { 380 /* Ensure we add the workgroup name for this 381 IP address as negative too. */ 382 add_failed_connection_entry( 383 domain, server, 384 NT_STATUS_UNSUCCESSFUL); 385 } 386 } 387 } 388 389 status = cldap_ping_list(ads, domain, ip_list, count); 390 391 SAFE_FREE(ip_list); 392 393 return status; 394 } 395 396 397 /********************************************************************** 398 resolve a name and perform an "ldap ping" using DNS 399 **********************************************************************/ 400 401 static NTSTATUS resolve_and_ping_dns(ADS_STRUCT *ads, const char *sitename, 402 const char *realm) 403 { 404 int count; 405 struct ip_service *ip_list; 406 NTSTATUS status = NT_STATUS_UNSUCCESSFUL; 407 408 DEBUG(6, ("resolve_and_ping_dns: (cldap) looking for realm '%s'\n", 409 realm)); 410 411 status = get_sorted_dc_list(realm, sitename, &ip_list, &count, 412 true); 413 if (!NT_STATUS_IS_OK(status)) { 414 return status; 415 } 416 417 status = cldap_ping_list(ads, realm, ip_list, count); 418 419 SAFE_FREE(ip_list); 420 421 return status; 422 } 423 424 /********************************************************************** 297 425 Try to find an AD dc using our internal name resolution routines 298 Try the realm first and then then workgroup name if netbios is not 426 Try the realm first and then then workgroup name if netbios is not 299 427 disabled 300 428 **********************************************************************/ … … 302 430 static NTSTATUS ads_find_dc(ADS_STRUCT *ads) 303 431 { 304 const char *c_domain ;432 const char *c_domain = ""; 305 433 const char *c_realm; 306 int count, i=0;307 struct ip_service *ip_list;308 const char *realm;309 const char *domain;310 bool got_realm = False;311 434 bool use_own_domain = False; 312 char *sitename ;435 char *sitename = NULL; 313 436 NTSTATUS status = NT_STATUS_UNSUCCESSFUL; 437 bool ok = false; 314 438 315 439 /* if the realm and workgroup are both empty, assume they are ours */ … … 318 442 c_realm = ads->server.realm; 319 443 320 if ( !c_realm || !*c_realm ) { 444 if (c_realm == NULL) 445 c_realm = ""; 446 447 if (!*c_realm) { 321 448 /* special case where no realm and no workgroup means our own */ 322 449 if ( !ads->server.workgroup || !*ads->server.workgroup ) { … … 326 453 } 327 454 328 if (c_realm && *c_realm) 329 got_realm = True; 330 331 /* we need to try once with the realm name and fallback to the 332 netbios domain name if we fail (if netbios has not been disabled */ 333 334 if ( !got_realm && !lp_disable_netbios() ) { 335 c_realm = ads->server.workgroup; 336 if (!c_realm || !*c_realm) { 337 if ( use_own_domain ) 338 c_realm = lp_workgroup(); 339 } 340 } 341 342 if ( !c_realm || !*c_realm ) { 343 DEBUG(0,("ads_find_dc: no realm or workgroup! Don't know what to do\n")); 455 if (!lp_disable_netbios()) { 456 if (use_own_domain) { 457 c_domain = lp_workgroup(); 458 } else { 459 c_domain = ads->server.workgroup; 460 if (!*c_realm && (!c_domain || !*c_domain)) { 461 c_domain = lp_workgroup(); 462 } 463 } 464 465 if (!c_domain) { 466 c_domain = ""; 467 } 468 } 469 470 if (!*c_realm && !*c_domain) { 471 DEBUG(0, ("ads_find_dc: no realm or workgroup! Don't know " 472 "what to do\n")); 344 473 return NT_STATUS_INVALID_PARAMETER; /* rather need MISSING_PARAMETER ... */ 345 474 } 346 347 if ( use_own_domain ) {348 c_domain = lp_workgroup();349 } else {350 c_domain = ads->server.workgroup;351 }352 353 realm = c_realm;354 domain = c_domain;355 475 356 476 /* … … 362 482 struct sockaddr_storage ip_out; 363 483 364 DEBUG(6,("ads_find_dc: (ldap) looking for %s '%s'\n", 365 (got_realm ? "realm" : "domain"), realm)); 366 367 if (get_dc_name(domain, realm, srv_name, &ip_out)) { 484 DEBUG(6, ("ads_find_dc: (ldap) looking for realm '%s'" 485 " and falling back to domain '%s'\n", 486 c_realm, c_domain)); 487 488 ok = get_dc_name(c_domain, c_realm, srv_name, &ip_out); 489 if (ok) { 368 490 /* 369 491 * we call ads_try_connect() to fill in the 370 492 * ads->config details 371 493 */ 372 if (ads_try_connect(ads, srv_name, false)) { 494 ok = ads_try_connect(ads, false, &ip_out); 495 if (ok) { 373 496 return NT_STATUS_OK; 374 497 } … … 378 501 } 379 502 380 sitename = sitename_fetch(realm); 381 382 again: 383 384 DEBUG(6,("ads_find_dc: (cldap) looking for %s '%s'\n", 385 (got_realm ? "realm" : "domain"), realm)); 386 387 status = get_sorted_dc_list(realm, sitename, &ip_list, &count, got_realm); 388 if (!NT_STATUS_IS_OK(status)) { 389 /* fall back to netbios if we can */ 390 if ( got_realm && !lp_disable_netbios() ) { 391 got_realm = False; 392 goto again; 393 } 394 395 SAFE_FREE(sitename); 396 return status; 397 } 398 399 /* if we fail this loop, then giveup since all the IP addresses returned were dead */ 400 for ( i=0; i<count; i++ ) { 401 char server[INET6_ADDRSTRLEN]; 402 403 print_sockaddr(server, sizeof(server), &ip_list[i].ss); 404 405 if ( !NT_STATUS_IS_OK(check_negative_conn_cache(realm, server)) ) 406 continue; 407 408 if (!got_realm) { 409 /* realm in this case is a workgroup name. We need 410 to ignore any IP addresses in the negative connection 411 cache that match ip addresses returned in the ad realm 412 case. It sucks that I have to reproduce the logic above... */ 413 c_realm = ads->server.realm; 414 if ( !c_realm || !*c_realm ) { 415 if ( !ads->server.workgroup || !*ads->server.workgroup ) { 416 c_realm = lp_realm(); 417 } 503 if (*c_realm) { 504 sitename = sitename_fetch(talloc_tos(), c_realm); 505 status = resolve_and_ping_dns(ads, sitename, c_realm); 506 507 if (NT_STATUS_IS_OK(status)) { 508 TALLOC_FREE(sitename); 509 return status; 510 } 511 512 /* In case we failed to contact one of our closest DC on our 513 * site we 514 * need to try to find another DC, retry with a site-less SRV 515 * DNS query 516 * - Guenther */ 517 518 if (sitename) { 519 DEBUG(3, ("ads_find_dc: failed to find a valid DC on " 520 "our site (%s), Trying to find another DC " 521 "for realm '%s' (domain '%s')\n", 522 sitename, c_realm, c_domain)); 523 namecache_delete(c_realm, 0x1C); 524 status = 525 resolve_and_ping_dns(ads, NULL, c_realm); 526 527 if (NT_STATUS_IS_OK(status)) { 528 TALLOC_FREE(sitename); 529 return status; 418 530 } 419 if (c_realm && *c_realm && 420 !NT_STATUS_IS_OK(check_negative_conn_cache(c_realm, server))) { 421 /* Ensure we add the workgroup name for this 422 IP address as negative too. */ 423 add_failed_connection_entry( realm, server, NT_STATUS_UNSUCCESSFUL ); 424 continue; 425 } 426 } 427 428 if ( ads_try_connect(ads, server, false) ) { 429 SAFE_FREE(ip_list); 430 SAFE_FREE(sitename); 431 return NT_STATUS_OK; 432 } 433 434 /* keep track of failures */ 435 add_failed_connection_entry( realm, server, NT_STATUS_UNSUCCESSFUL ); 436 } 437 438 SAFE_FREE(ip_list); 439 440 /* In case we failed to contact one of our closest DC on our site we 441 * need to try to find another DC, retry with a site-less SRV DNS query 442 * - Guenther */ 443 444 if (sitename) { 445 DEBUG(1,("ads_find_dc: failed to find a valid DC on our site (%s), " 446 "trying to find another DC\n", sitename)); 447 SAFE_FREE(sitename); 448 namecache_delete(realm, 0x1C); 449 goto again; 450 } 451 452 return NT_STATUS_NO_LOGON_SERVERS; 453 } 454 455 /********************************************************************* 456 *********************************************************************/ 457 458 static NTSTATUS ads_lookup_site(void) 459 { 460 ADS_STRUCT *ads = NULL; 461 ADS_STATUS ads_status; 462 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; 463 464 ads = ads_init(lp_realm(), NULL, NULL); 465 if (!ads) { 466 return NT_STATUS_NO_MEMORY; 467 } 468 469 /* The NO_BIND here will find a DC and set the client site 470 but not establish the TCP connection */ 471 472 ads->auth.flags = ADS_AUTH_NO_BIND; 473 ads_status = ads_connect(ads); 474 if (!ADS_ERR_OK(ads_status)) { 475 DEBUG(4, ("ads_lookup_site: ads_connect to our realm failed! (%s)\n", 476 ads_errstr(ads_status))); 477 } 478 nt_status = ads_ntstatus(ads_status); 479 480 if (ads) { 481 ads_destroy(&ads); 482 } 483 484 return nt_status; 485 } 486 487 /********************************************************************* 488 *********************************************************************/ 489 490 static const char* host_dns_domain(const char *fqdn) 491 { 492 const char *p = fqdn; 493 494 /* go to next char following '.' */ 495 496 if ((p = strchr_m(fqdn, '.')) != NULL) { 497 p++; 498 } 499 500 return p; 501 } 502 503 504 /** 505 * Connect to the Global Catalog server 506 * @param ads Pointer to an existing ADS_STRUCT 507 * @return status of connection 508 * 509 * Simple wrapper around ads_connect() that fills in the 510 * GC ldap server information 511 **/ 512 513 ADS_STATUS ads_connect_gc(ADS_STRUCT *ads) 514 { 515 TALLOC_CTX *frame = talloc_stackframe(); 516 struct dns_rr_srv *gcs_list; 517 int num_gcs; 518 char *realm = ads->server.realm; 519 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; 520 ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); 521 int i; 522 bool done = false; 523 char *sitename = NULL; 524 525 if (!realm) 526 realm = lp_realm(); 527 528 if ((sitename = sitename_fetch(realm)) == NULL) { 529 ads_lookup_site(); 530 sitename = sitename_fetch(realm); 531 } 532 533 do { 534 /* We try once with a sitename and once without 535 (unless we don't have a sitename and then we're 536 done */ 537 538 if (sitename == NULL) 539 done = true; 540 541 nt_status = ads_dns_query_gcs(frame, realm, sitename, 542 &gcs_list, &num_gcs); 543 544 SAFE_FREE(sitename); 545 546 if (!NT_STATUS_IS_OK(nt_status)) { 547 ads_status = ADS_ERROR_NT(nt_status); 548 goto done; 549 } 550 551 /* Loop until we get a successful connection or have gone 552 through them all. When connecting a GC server, make sure that 553 the realm is the server's DNS name and not the forest root */ 554 555 for (i=0; i<num_gcs; i++) { 556 ads->server.gc = true; 557 ads->server.ldap_server = SMB_STRDUP(gcs_list[i].hostname); 558 ads->server.realm = SMB_STRDUP(host_dns_domain(ads->server.ldap_server)); 559 ads_status = ads_connect(ads); 560 if (ADS_ERR_OK(ads_status)) { 561 /* Reset the bind_dn to "". A Global Catalog server 562 may host multiple domain trees in a forest. 563 Windows 2003 GC server will accept "" as the search 564 path to imply search all domain trees in the forest */ 565 566 SAFE_FREE(ads->config.bind_path); 567 ads->config.bind_path = SMB_STRDUP(""); 568 569 570 goto done; 571 } 572 SAFE_FREE(ads->server.ldap_server); 573 SAFE_FREE(ads->server.realm); 574 } 575 576 TALLOC_FREE(gcs_list); 577 num_gcs = 0; 578 } while (!done); 579 580 done: 581 SAFE_FREE(sitename); 582 talloc_destroy(frame); 583 584 return ads_status; 585 } 586 587 531 } 532 533 TALLOC_FREE(sitename); 534 } 535 536 /* try netbios as fallback - if permitted, 537 or if configuration specifically requests it */ 538 if (*c_domain) { 539 if (*c_realm) { 540 DEBUG(3, ("ads_find_dc: falling back to netbios " 541 "name resolution for domain '%s' (realm '%s')\n", 542 c_domain, c_realm)); 543 } 544 545 status = resolve_and_ping_netbios(ads, c_domain, c_realm); 546 if (NT_STATUS_IS_OK(status)) { 547 return status; 548 } 549 } 550 551 DEBUG(1, ("ads_find_dc: " 552 "name resolution for realm '%s' (domain '%s') failed: %s\n", 553 c_realm, c_domain, nt_errstr(status))); 554 return status; 555 } 588 556 /** 589 557 * Connect to the LDAP server … … 611 579 } 612 580 613 if (ads->server.ldap_server) 614 { 615 if (ads_try_connect(ads, ads->server.ldap_server, ads->server.gc)) { 581 if (ads->server.ldap_server) { 582 bool ok = false; 583 struct sockaddr_storage ss; 584 585 ok = resolve_name(ads->server.ldap_server, &ss, 0x20, true); 586 if (!ok) { 587 DEBUG(5,("ads_connect: unable to resolve name %s\n", 588 ads->server.ldap_server)); 589 status = ADS_ERROR_NT(NT_STATUS_NOT_FOUND); 590 goto out; 591 } 592 ok = ads_try_connect(ads, ads->server.gc, &ss); 593 if (ok) { 616 594 goto got_connection; 617 595 } … … 644 622 and not servicePrincipalName; found by Guenther Deschner */ 645 623 646 if (asprintf(&ads->auth.user_name, "%s$", global_myname() ) == -1) {624 if (asprintf(&ads->auth.user_name, "%s$", lp_netbios_name() ) == -1) { 647 625 DEBUG(0,("ads_connect: asprintf fail.\n")); 648 626 ads->auth.user_name = NULL; … … 658 636 ads->auth.kdc_server = SMB_STRDUP(addr); 659 637 } 660 661 #if KRB5_DNS_HACK662 /* this is a really nasty hack to avoid ADS DNS problems. It needs a patch663 to MIT kerberos to work (tridge) */664 {665 char *env = NULL;666 if (asprintf(&env, "KRB5_KDC_ADDRESS_%s", ads->config.realm) > 0) {667 setenv(env, ads->auth.kdc_server, 1);668 free(env);669 }670 }671 #endif672 638 673 639 /* If the caller() requested no LDAP bind, then we are done */ … … 686 652 /* Otherwise setup the TCP LDAP session */ 687 653 688 ads->ldap.ld = ldap_open_with_timeout(ads->config.ldap_server_name, 654 ads->ldap.ld = ldap_open_with_timeout(addr, 655 &ads->ldap.ss, 689 656 ads->ldap.port, lp_ldap_timeout()); 690 657 if (ads->ldap.ld == NULL) { … … 703 670 704 671 if ( lp_ldap_ssl_ads() ) { 705 status = ADS_ERROR(smb _ldap_start_tls(ads->ldap.ld, version));672 status = ADS_ERROR(smbldap_start_tls(ads->ldap.ld, version)); 706 673 if (!ADS_ERR_OK(status)) { 707 674 goto out; … … 782 749 if (!in_val) return NULL; 783 750 784 value = TALLOC_ZERO_P(ctx, struct berval);751 value = talloc_zero(ctx, struct berval); 785 752 if (value == NULL) 786 753 return NULL; … … 788 755 789 756 value->bv_len = in_val->bv_len; 790 value->bv_val = (char *) TALLOC_MEMDUP(ctx, in_val->bv_val,757 value->bv_val = (char *)talloc_memdup(ctx, in_val->bv_val, 791 758 in_val->bv_len); 792 759 return value; … … 805 772 for (i=0; in_vals[i]; i++) 806 773 ; /* count values */ 807 values = TALLOC_ZERO_ARRAY(ctx, struct berval *, i+1);774 values = talloc_zero_array(ctx, struct berval *, i+1); 808 775 if (!values) return NULL; 809 776 … … 826 793 for (i=0; in_vals[i]; i++) 827 794 ; /* count values */ 828 values = TALLOC_ZERO_ARRAY(ctx, char *, i+1);795 values = talloc_zero_array(ctx, char *, i+1); 829 796 if (!values) return NULL; 830 797 … … 850 817 for (i=0; in_vals[i]; i++) 851 818 ; /* count values */ 852 values = TALLOC_ZERO_ARRAY(ctx, char *, i+1);819 values = talloc_zero_array(ctx, char *, i+1); 853 820 if (!values) return NULL; 854 821 … … 938 905 } 939 906 ber_flatten(cookie_be, &cookie_bv); 940 PagedResults.ldctl_oid = CONST_DISCARD(char *, ADS_PAGE_CTL_OID);907 PagedResults.ldctl_oid = discard_const_p(char, ADS_PAGE_CTL_OID); 941 908 PagedResults.ldctl_iscritical = (char) 1; 942 909 PagedResults.ldctl_value.bv_len = cookie_bv->bv_len; 943 910 PagedResults.ldctl_value.bv_val = cookie_bv->bv_val; 944 911 945 NoReferrals.ldctl_oid = CONST_DISCARD(char *, ADS_NO_REFERRALS_OID);912 NoReferrals.ldctl_oid = discard_const_p(char, ADS_NO_REFERRALS_OID); 946 913 NoReferrals.ldctl_iscritical = (char) 0; 947 914 NoReferrals.ldctl_value.bv_len = 0; 948 NoReferrals.ldctl_value.bv_val = CONST_DISCARD(char *, "");915 NoReferrals.ldctl_value.bv_val = discard_const_p(char, ""); 949 916 950 917 if (external_control && … … 952 919 strequal(external_control->control, ADS_SD_FLAGS_OID))) { 953 920 954 ExternalCtrl.ldctl_oid = CONST_DISCARD(char *, external_control->control);921 ExternalCtrl.ldctl_oid = discard_const_p(char, external_control->control); 955 922 ExternalCtrl.ldctl_iscritical = (char) external_control->critical; 956 923 … … 1013 980 DEBUG(3,("ads_do_paged_search_args: ldap_search_with_timeout(%s) -> %s\n", expr, 1014 981 ldap_err2string(rc))); 982 if (rc == LDAP_OTHER) { 983 char *ldap_errmsg; 984 int ret; 985 986 ret = ldap_parse_result(ads->ldap.ld, 987 *res, 988 NULL, 989 NULL, 990 &ldap_errmsg, 991 NULL, 992 NULL, 993 0); 994 if (ret == LDAP_SUCCESS) { 995 DEBUG(3, ("ldap_search_with_timeout(%s) " 996 "error: %s\n", expr, ldap_errmsg)); 997 ldap_memfree(ldap_errmsg); 998 } 999 } 1015 1000 goto done; 1016 1001 } … … 1097 1082 while (cookie) { 1098 1083 LDAPMessage *res2 = NULL; 1099 ADS_STATUS status2;1100 1084 LDAPMessage *msg, *next; 1101 1085 1102 status 2 = ads_do_paged_search_args(ads, bind_path, scope, expr,1086 status = ads_do_paged_search_args(ads, bind_path, scope, expr, 1103 1087 attrs, args, &res2, &count, &cookie); 1104 1105 if (!ADS_ERR_OK(status2)) break; 1088 if (!ADS_ERR_OK(status)) { 1089 /* Ensure we free all collected results */ 1090 ads_msgfree(ads, *res); 1091 *res = NULL; 1092 break; 1093 } 1106 1094 1107 1095 /* this relies on the way that ldap_add_result_entry() works internally. I hope … … 1131 1119 ADS_STATUS ads_do_search_all_sd_flags(ADS_STRUCT *ads, const char *bind_path, 1132 1120 int scope, const char *expr, 1133 const char **attrs, uint32 sd_flags,1121 const char **attrs, uint32_t sd_flags, 1134 1122 LDAPMessage **res) 1135 1123 { … … 1357 1345 ADS_STATUS status; 1358 1346 char *expr; 1359 const char *attrs[] = {"*", " nTSecurityDescriptor", NULL};1347 const char *attrs[] = {"*", "msDS-SupportedEncryptionTypes", "nTSecurityDescriptor", NULL}; 1360 1348 1361 1349 *res = NULL; … … 1383 1371 LDAPMod **mods; 1384 1372 1385 if ((mods = TALLOC_ZERO_ARRAY(ctx, LDAPMod *, ADS_MODLIST_ALLOC_SIZE + 1)))1373 if ((mods = talloc_zero_array(ctx, LDAPMod *, ADS_MODLIST_ALLOC_SIZE + 1))) 1386 1374 /* -1 is safety to make sure we don't go over the end. 1387 1375 need to reset it to NULL before doing ldap modify */ … … 1399 1387 const void *_invals) 1400 1388 { 1401 const void **invals = (const void **)_invals;1402 1389 int curmod; 1403 1390 LDAPMod **modlist = (LDAPMod **) *mods; … … 1405 1392 char **char_values = NULL; 1406 1393 1407 if (! invals) {1394 if (!_invals) { 1408 1395 mod_op = LDAP_MOD_DELETE; 1409 1396 } else { 1410 if (mod_op & LDAP_MOD_BVALUES) 1411 ber_values = ads_dup_values(ctx, 1412 (const struct berval **)invals); 1413 else 1414 char_values = ads_push_strvals(ctx, 1415 (const char **) invals); 1397 if (mod_op & LDAP_MOD_BVALUES) { 1398 const struct berval **b; 1399 b = discard_const_p(const struct berval *, _invals); 1400 ber_values = ads_dup_values(ctx, b); 1401 } else { 1402 const char **c; 1403 c = discard_const_p(const char *, _invals); 1404 char_values = ads_push_strvals(ctx, c); 1405 } 1416 1406 } 1417 1407 … … 1420 1410 curmod++); 1421 1411 if (modlist[curmod] == (LDAPMod *) -1) { 1422 if (!(modlist = TALLOC_REALLOC_ARRAY(ctx, modlist, LDAPMod *,1412 if (!(modlist = talloc_realloc(ctx, modlist, LDAPMod *, 1423 1413 curmod+ADS_MODLIST_ALLOC_SIZE+1))) 1424 1414 return ADS_ERROR(LDAP_NO_MEMORY); … … 1429 1419 } 1430 1420 1431 if (!(modlist[curmod] = TALLOC_ZERO_P(ctx, LDAPMod)))1421 if (!(modlist[curmod] = talloc_zero(ctx, LDAPMod))) 1432 1422 return ADS_ERROR(LDAP_NO_MEMORY); 1433 1423 modlist[curmod]->mod_type = talloc_strdup(ctx, name); … … 1505 1495 #endif 1506 1496 1497 static void ads_print_error(int ret, LDAP *ld) 1498 { 1499 if (ret != 0) { 1500 char *ld_error = NULL; 1501 ldap_get_option(ld, LDAP_OPT_ERROR_STRING, &ld_error); 1502 DEBUG(10,("AD LDAP failure %d (%s):\n%s\n", ret, 1503 ldap_err2string(ret), ld_error)); 1504 SAFE_FREE(ld_error); 1505 } 1506 } 1507 1507 1508 /** 1508 1509 * Perform an ldap modify … … 1522 1523 */ 1523 1524 LDAPControl PermitModify = { 1524 CONST_DISCARD(char *, ADS_PERMIT_MODIFY_OID),1525 discard_const_p(char, ADS_PERMIT_MODIFY_OID), 1525 1526 {0, NULL}, 1526 1527 (char) 1}; … … 1540 1541 ret = ldap_modify_ext_s(ads->ldap.ld, utf8_dn, 1541 1542 (LDAPMod **) mods, controls, NULL); 1543 ads_print_error(ret, ads->ldap.ld); 1542 1544 TALLOC_FREE(utf8_dn); 1543 1545 return ADS_ERROR(ret); … … 1568 1570 1569 1571 ret = ldap_add_s(ads->ldap.ld, utf8_dn, (LDAPMod**)mods); 1572 ads_print_error(ret, ads->ldap.ld); 1570 1573 TALLOC_FREE(utf8_dn); 1571 1574 return ADS_ERROR(ret); … … 1589 1592 1590 1593 ret = ldap_delete_s(ads->ldap.ld, utf8_dn); 1594 ads_print_error(ret, ads->ldap.ld); 1591 1595 TALLOC_FREE(utf8_dn); 1592 1596 return ADS_ERROR(ret); … … 1740 1744 **/ 1741 1745 1742 uint32 ads_get_kvno(ADS_STRUCT *ads, const char *account_name)1746 uint32_t ads_get_kvno(ADS_STRUCT *ads, const char *account_name) 1743 1747 { 1744 1748 LDAPMessage *res = NULL; 1745 uint32 kvno = (uint32)-1; /* -1 indicates a failure */1749 uint32_t kvno = (uint32_t)-1; /* -1 indicates a failure */ 1746 1750 char *filter; 1747 1751 const char *attrs[] = {"msDS-KeyVersionNumber", NULL}; … … 1878 1882 1879 1883 /** 1884 * @brief Search for an element in a string array. 1885 * 1886 * @param[in] el_array The string array to search. 1887 * 1888 * @param[in] num_el The number of elements in the string array. 1889 * 1890 * @param[in] el The string to search. 1891 * 1892 * @return True if found, false if not. 1893 */ 1894 bool ads_element_in_array(const char **el_array, size_t num_el, const char *el) 1895 { 1896 size_t i; 1897 1898 if (el_array == NULL || num_el == 0 || el == NULL) { 1899 return false; 1900 } 1901 1902 for (i = 0; i < num_el && el_array[i] != NULL; i++) { 1903 int cmp; 1904 1905 cmp = strcasecmp_m(el_array[i], el); 1906 if (cmp == 0) { 1907 return true; 1908 } 1909 } 1910 1911 return false; 1912 } 1913 1914 /** 1915 * @brief This gets the service principal names of an existing computer account. 1916 * 1917 * @param[in] mem_ctx The memory context to use to allocate the spn array. 1918 * 1919 * @param[in] ads The ADS context to use. 1920 * 1921 * @param[in] machine_name The NetBIOS name of the computer, which is used to 1922 * identify the computer account. 1923 * 1924 * @param[in] spn_array A pointer to store the array for SPNs. 1925 * 1926 * @param[in] num_spns The number of principals stored in the array. 1927 * 1928 * @return 0 on success, or a ADS error if a failure occured. 1929 */ 1930 ADS_STATUS ads_get_service_principal_names(TALLOC_CTX *mem_ctx, 1931 ADS_STRUCT *ads, 1932 const char *machine_name, 1933 char ***spn_array, 1934 size_t *num_spns) 1935 { 1936 ADS_STATUS status; 1937 LDAPMessage *res = NULL; 1938 int count; 1939 1940 status = ads_find_machine_acct(ads, 1941 &res, 1942 machine_name); 1943 if (!ADS_ERR_OK(status)) { 1944 DEBUG(1,("Host Account for %s not found... skipping operation.\n", 1945 machine_name)); 1946 return status; 1947 } 1948 1949 count = ads_count_replies(ads, res); 1950 if (count != 1) { 1951 status = ADS_ERROR(LDAP_NO_SUCH_OBJECT); 1952 goto done; 1953 } 1954 1955 *spn_array = ads_pull_strings(ads, 1956 mem_ctx, 1957 res, 1958 "servicePrincipalName", 1959 num_spns); 1960 if (*spn_array == NULL) { 1961 DEBUG(1, ("Host account for %s does not have service principal " 1962 "names.\n", 1963 machine_name)); 1964 status = ADS_ERROR(LDAP_NO_SUCH_OBJECT); 1965 goto done; 1966 } 1967 1968 done: 1969 ads_msgfree(ads, res); 1970 1971 return status; 1972 } 1973 1974 /** 1880 1975 * This adds a service principal name to an existing computer account 1881 1976 * (found by hostname) in AD. … … 1921 2016 return ADS_ERROR(LDAP_NO_MEMORY); 1922 2017 } 1923 strlower_m(&psp1[strlen(spn) + 1]); 2018 if (!strlower_m(&psp1[strlen(spn) + 1])) { 2019 ret = ADS_ERROR(LDAP_NO_MEMORY); 2020 goto out; 2021 } 1924 2022 servicePrincipalName[0] = psp1; 1925 2023 … … 1934 2032 goto out; 1935 2033 } 1936 strlower_m(&psp2[strlen(spn) + 1]); 2034 if (!strlower_m(&psp2[strlen(spn) + 1])) { 2035 ret = ADS_ERROR(LDAP_NO_MEMORY); 2036 goto out; 2037 } 1937 2038 servicePrincipalName[1] = psp2; 1938 2039 … … 1977 2078 **/ 1978 2079 1979 ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, const char *machine_name, 1980 const char *org_unit) 2080 ADS_STATUS ads_create_machine_acct(ADS_STRUCT *ads, 2081 const char *machine_name, 2082 const char *org_unit, 2083 uint32_t etype_list) 1981 2084 { 1982 2085 ADS_STATUS ret; … … 1989 2092 "user", "computer", NULL}; 1990 2093 LDAPMessage *res = NULL; 1991 uint32 acct_control = ( UF_WORKSTATION_TRUST_ACCOUNT |\2094 uint32_t acct_control = ( UF_WORKSTATION_TRUST_ACCOUNT |\ 1992 2095 UF_DONT_EXPIRE_PASSWD |\ 1993 2096 UF_ACCOUNTDISABLE ); 2097 uint32_t func_level = 0; 2098 2099 ret = ads_domain_func_level(ads, &func_level); 2100 if (!ADS_ERR_OK(ret)) { 2101 return ret; 2102 } 1994 2103 1995 2104 if (!(ctx = talloc_init("ads_add_machine_acct"))) … … 2026 2135 ads_mod_strlist(ctx, &mods, "objectClass", objectClass); 2027 2136 ads_mod_str(ctx, &mods, "userAccountControl", controlstr); 2137 2138 if (func_level >= DS_DOMAIN_FUNCTION_2008) { 2139 const char *etype_list_str; 2140 2141 etype_list_str = talloc_asprintf(ctx, "%d", (int)etype_list); 2142 if (etype_list_str == NULL) { 2143 goto done; 2144 } 2145 ads_mod_str(ctx, &mods, "msDS-SupportedEncryptionTypes", 2146 etype_list_str); 2147 } 2028 2148 2029 2149 ret = ads_gen_add(ads, new_dn, mods); … … 2149 2269 struct dom_sid sid; 2150 2270 fstring tmp; 2151 if (!sid_parse(values[i]->bv_val, values[i]->bv_len, &sid)) { 2271 if (!sid_parse((const uint8_t *)values[i]->bv_val, 2272 values[i]->bv_len, &sid)) { 2152 2273 return; 2153 2274 } … … 2165 2286 NTSTATUS status; 2166 2287 2167 status = unmarshall_sec_desc(talloc_tos(), (uint8 *)values[0]->bv_val,2288 status = unmarshall_sec_desc(talloc_tos(), (uint8_t *)values[0]->bv_val, 2168 2289 values[0]->bv_len, &psd); 2169 2290 if (!NT_STATUS_IS_OK(status)) { … … 2224 2345 2225 2346 for (i=0; handlers[i].name; i++) { 2226 if ( StrCaseCmp(handlers[i].name, field) == 0) {2347 if (strcasecmp_m(handlers[i].name, field) == 0) { 2227 2348 if (!values) /* first time, indicate string or not */ 2228 2349 return handlers[i].string; … … 2284 2405 (LDAPMessage *)msg,b)) { 2285 2406 struct berval **ber_vals; 2286 char **str_vals, **utf8_vals; 2407 char **str_vals; 2408 char **utf8_vals; 2287 2409 char *field; 2288 2410 bool string; … … 2299 2421 2300 2422 if (string) { 2423 const char **p; 2424 2301 2425 utf8_vals = ldap_get_values(ads->ldap.ld, 2302 2426 (LDAPMessage *)msg, field); 2303 str_vals = ads_pull_strvals(ctx,2304 (const char **) utf8_vals);2427 p = discard_const_p(const char *, utf8_vals); 2428 str_vals = ads_pull_strvals(ctx, p); 2305 2429 fn(ads, field, (void **) str_vals, data_area); 2306 2430 ldap_value_free(utf8_vals); … … 2429 2553 *num_values = ldap_count_values(values); 2430 2554 2431 ret = TALLOC_ARRAY(mem_ctx, char *, *num_values + 1);2555 ret = talloc_array(mem_ctx, char *, *num_values + 1); 2432 2556 if (!ret) { 2433 2557 ldap_value_free(values); … … 2542 2666 } 2543 2667 2544 strings = TALLOC_REALLOC_ARRAY(mem_ctx, current_strings, char *,2668 strings = talloc_realloc(mem_ctx, current_strings, char *, 2545 2669 *num_strings + num_new_strings); 2546 2670 … … 2578 2702 2579 2703 /** 2580 * pull a single uint32 from a ADS result2704 * pull a single uint32_t from a ADS result 2581 2705 * @param ads connection to ads server 2582 2706 * @param msg Results of search … … 2586 2710 */ 2587 2711 bool ads_pull_uint32(ADS_STRUCT *ads, LDAPMessage *msg, const char *field, 2588 uint32 *v)2712 uint32_t *v) 2589 2713 { 2590 2714 char **values; … … 2665 2789 2666 2790 if (i) { 2667 (*sids) = TALLOC_ARRAY(mem_ctx, struct dom_sid, i);2791 (*sids) = talloc_array(mem_ctx, struct dom_sid, i); 2668 2792 if (!(*sids)) { 2669 2793 ldap_value_free_len(values); … … 2676 2800 count = 0; 2677 2801 for (i=0; values[i]; i++) { 2678 ret = sid_parse(values[i]->bv_val, values[i]->bv_len, &(*sids)[count]); 2802 ret = sid_parse((const uint8_t *)values[i]->bv_val, 2803 values[i]->bv_len, &(*sids)[count]); 2679 2804 if (ret) { 2680 2805 DEBUG(10, ("pulling SID: %s\n", … … 2711 2836 NTSTATUS status; 2712 2837 status = unmarshall_sec_desc(mem_ctx, 2713 (uint8 *)values[0]->bv_val,2838 (uint8_t *)values[0]->bv_val, 2714 2839 values[0]->bv_len, sd); 2715 2840 if (!NT_STATUS_IS_OK(status)) { … … 2761 2886 * @return status of search 2762 2887 **/ 2763 ADS_STATUS ads_USN(ADS_STRUCT *ads, uint32 *usn)2888 ADS_STATUS ads_USN(ADS_STRUCT *ads, uint32_t *usn) 2764 2889 { 2765 2890 const char *attrs[] = {"highestCommittedUSN", NULL}; … … 2853 2978 if (ads->config.current_time != 0) { 2854 2979 ads->auth.time_offset = ads->config.current_time - time(NULL); 2855 DEBUG(4,(" time offset is %d seconds\n", ads->auth.time_offset));2980 DEBUG(4,("KDC time offset is %d seconds\n", ads->auth.time_offset)); 2856 2981 } 2857 2982 … … 2873 2998 ********************************************************************/ 2874 2999 2875 ADS_STATUS ads_domain_func_level(ADS_STRUCT *ads, uint32 *val)3000 ADS_STATUS ads_domain_func_level(ADS_STRUCT *ads, uint32_t *val) 2876 3001 { 2877 3002 const char *attrs[] = {"domainFunctionality", NULL}; … … 3143 3268 for (msg = ads_first_entry(ads, res); msg; 3144 3269 msg = ads_next_entry(ads, msg)) { 3145 3270 const char **p = discard_const_p(const char *, *ous); 3146 3271 char *dn = NULL; 3147 3272 … … 3152 3277 } 3153 3278 3154 if (!add_string_to_array(mem_ctx, dn, 3155 (const char ***)ous, 3156 (int *)num_ous)) { 3279 if (!add_string_to_array(mem_ctx, dn, &p, num_ous)) { 3157 3280 TALLOC_FREE(dn); 3158 3281 ads_msgfree(ads, res); … … 3161 3284 3162 3285 TALLOC_FREE(dn); 3286 *ous = discard_const_p(char *, p); 3163 3287 } 3164 3288 … … 3242 3366 } 3243 3367 3244 if (!sid_parse( buf, buf_len, sid)) {3368 if (!sid_parse((const uint8_t *)buf, buf_len, sid)) { 3245 3369 DEBUG(10,("failed to parse sid\n")); 3246 3370 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); … … 3254 3378 3255 3379 return ADS_ERROR_NT(NT_STATUS_OK); 3256 }3257 3258 /**3259 * pull an array of struct dom_sids from a ADS result3260 * @param ads connection to ads server3261 * @param mem_ctx TALLOC_CTX for allocating sid array3262 * @param msg Results of search3263 * @param field Attribute to retrieve3264 * @param flags string type of extended_dn3265 * @param sids pointer to sid array to allocate3266 * @return the count of SIDs pulled3267 **/3268 int ads_pull_sids_from_extendeddn(ADS_STRUCT *ads,3269 TALLOC_CTX *mem_ctx,3270 LDAPMessage *msg,3271 const char *field,3272 enum ads_extended_dn_flags flags,3273 struct dom_sid **sids)3274 {3275 int i;3276 ADS_STATUS rc;3277 size_t dn_count, ret_count = 0;3278 char **dn_strings;3279 3280 if ((dn_strings = ads_pull_strings(ads, mem_ctx, msg, field,3281 &dn_count)) == NULL) {3282 return 0;3283 }3284 3285 (*sids) = TALLOC_ZERO_ARRAY(mem_ctx, struct dom_sid, dn_count + 1);3286 if (!(*sids)) {3287 TALLOC_FREE(dn_strings);3288 return 0;3289 }3290 3291 for (i=0; i<dn_count; i++) {3292 rc = ads_get_sid_from_extended_dn(mem_ctx, dn_strings[i],3293 flags, &(*sids)[i]);3294 if (!ADS_ERR_OK(rc)) {3295 if (NT_STATUS_EQUAL(ads_ntstatus(rc),3296 NT_STATUS_NOT_FOUND)) {3297 continue;3298 }3299 else {3300 TALLOC_FREE(*sids);3301 TALLOC_FREE(dn_strings);3302 return 0;3303 }3304 }3305 ret_count++;3306 }3307 3308 TALLOC_FREE(dn_strings);3309 3310 return ret_count;3311 3380 } 3312 3381 … … 3321 3390 char *name = NULL; 3322 3391 3323 status = ads_find_machine_acct(ads, &res, global_myname());3392 status = ads_find_machine_acct(ads, &res, lp_netbios_name()); 3324 3393 if (!ADS_ERR_OK(status)) { 3325 3394 DEBUG(0,("ads_get_dnshostname: Failed to find account for %s\n", 3326 global_myname()));3395 lp_netbios_name())); 3327 3396 goto out; 3328 3397 } … … 3356 3425 if (!ADS_ERR_OK(status)) { 3357 3426 DEBUG(0,("ads_get_upn: Failed to find account for %s\n", 3358 global_myname()));3427 lp_netbios_name())); 3359 3428 goto out; 3360 3429 } … … 3385 3454 char *name = NULL; 3386 3455 3387 status = ads_find_machine_acct(ads, &res, global_myname());3456 status = ads_find_machine_acct(ads, &res, lp_netbios_name()); 3388 3457 if (!ADS_ERR_OK(status)) { 3389 3458 DEBUG(0,("ads_get_dnshostname: Failed to find account for %s\n", 3390 global_myname()));3459 lp_netbios_name())); 3391 3460 goto out; 3392 3461 } … … 3420 3489 **/ 3421 3490 ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *machine_name, 3422 uint32 account_type, const char *org_unit)3491 uint32_t account_type, const char *org_unit) 3423 3492 { 3424 3493 ADS_STATUS status; … … 3481 3550 pldap_control[0] = &ldap_control; 3482 3551 memset(&ldap_control, 0, sizeof(LDAPControl)); 3483 ldap_control.ldctl_oid = (char *)LDAP_SERVER_TREE_DELETE_OID;3552 ldap_control.ldctl_oid = discard_const_p(char, LDAP_SERVER_TREE_DELETE_OID); 3484 3553 3485 3554 /* hostname must be lowercase */ 3486 3555 host = SMB_STRDUP(hostname); 3487 strlower_m(host); 3556 if (!strlower_m(host)) { 3557 SAFE_FREE(host); 3558 return ADS_ERROR_SYSTEM(EINVAL); 3559 } 3488 3560 3489 3561 status = ads_find_machine_acct(ads, &res, host); … … 3613 3685 struct dom_sid tmp_user_sid; 3614 3686 struct dom_sid tmp_primary_group_sid; 3615 uint32 pgid;3687 uint32_t pgid; 3616 3688 const char *attrs[] = { 3617 3689 "objectSid", … … 3695 3767 * @param mem_ctx TALLOC_CTX for allocating sid array 3696 3768 * @param samaccountname to search 3697 * @param uac_ret uint32 pointer userAccountControl attribute value3769 * @param uac_ret uint32_t pointer userAccountControl attribute value 3698 3770 * @param dn_ret pointer to dn 3699 3771 * @return status of token query … … 3702 3774 TALLOC_CTX *mem_ctx, 3703 3775 const char *samaccountname, 3704 uint32 *uac_ret,3776 uint32_t *uac_ret, 3705 3777 const char **dn_ret) 3706 3778 { … … 3710 3782 LDAPMessage *res = NULL; 3711 3783 char *dn = NULL; 3712 uint32 uac = 0;3784 uint32_t uac = 0; 3713 3785 3714 3786 filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)(sAMAccountName=%s))", … … 3868 3940 char *ou_string; 3869 3941 3870 exploded_dn = ldap_explode_dn(*account_ou, 0); 3871 if (exploded_dn) { 3872 ldap_value_free(exploded_dn); 3873 return ADS_SUCCESS; 3942 if (account_ou == NULL) { 3943 return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); 3944 } 3945 3946 if (*account_ou != NULL) { 3947 exploded_dn = ldap_explode_dn(*account_ou, 0); 3948 if (exploded_dn) { 3949 ldap_value_free(exploded_dn); 3950 return ADS_SUCCESS; 3951 } 3874 3952 } 3875 3953 -
vendor/current/source3/libads/ldap_printer.c
r740 r988 23 23 #include "../librpc/gen_ndr/ndr_spoolss_c.h" 24 24 #include "rpc_client/cli_spoolss.h" 25 #include "registry/reg_objects.h" 25 #include "registry.h" 26 #include "libcli/registry/util_reg.h" 26 27 27 28 #ifdef HAVE_ADS … … 115 116 map a REG_SZ to an ldap mod 116 117 */ 117 static bool map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods, 118 struct regval_blob *value) 118 static bool map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods, 119 const char *name, struct registry_value *value) 120 { 121 const char *str_value = NULL; 122 ADS_STATUS status; 123 124 if (value->type != REG_SZ) 125 return false; 126 127 if (value->data.length && value->data.data) { 128 if (!pull_reg_sz(ctx, &value->data, &str_value)) { 129 return false; 130 } 131 status = ads_mod_str(ctx, mods, name, str_value); 132 return ADS_ERR_OK(status); 133 } 134 return true; 135 } 136 137 /* 138 map a REG_DWORD to an ldap mod 139 */ 140 static bool map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods, 141 const char *name, struct registry_value *value) 119 142 { 120 143 char *str_value = NULL; 121 size_t converted_size; 122 ADS_STATUS status; 123 124 if (regval_type(value) != REG_SZ) 125 return false; 126 127 if (regval_size(value) && *((smb_ucs2_t *) regval_data_p(value))) { 128 if (!pull_ucs2_talloc(ctx, &str_value, 129 (const smb_ucs2_t *) regval_data_p(value), 130 &converted_size)) 131 { 144 ADS_STATUS status; 145 146 if (value->type != REG_DWORD) { 147 return false; 148 } 149 if (value->data.length != sizeof(uint32_t)) { 150 return false; 151 } 152 str_value = talloc_asprintf(ctx, "%d", IVAL(value->data.data, 0)); 153 if (!str_value) { 154 return false; 155 } 156 status = ads_mod_str(ctx, mods, name, str_value); 157 return ADS_ERR_OK(status); 158 } 159 160 /* 161 map a boolean REG_BINARY to an ldap mod 162 */ 163 static bool map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods, 164 const char *name, struct registry_value *value) 165 { 166 const char *str_value; 167 ADS_STATUS status; 168 169 if (value->type != REG_BINARY) { 170 return false; 171 } 172 if (value->data.length != 1) { 173 return false; 174 } 175 176 str_value = *value->data.data ? "TRUE" : "FALSE"; 177 178 status = ads_mod_str(ctx, mods, name, str_value); 179 return ADS_ERR_OK(status); 180 } 181 182 /* 183 map a REG_MULTI_SZ to an ldap mod 184 */ 185 static bool map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods, 186 const char *name, struct registry_value *value) 187 { 188 const char **str_values = NULL; 189 ADS_STATUS status; 190 191 if (value->type != REG_MULTI_SZ) { 192 return false; 193 } 194 195 if (value->data.length && value->data.data) { 196 if (!pull_reg_multi_sz(ctx, &value->data, &str_values)) { 132 197 return false; 133 198 } 134 status = ads_mod_str (ctx, mods, regval_name(value), str_value);199 status = ads_mod_strlist(ctx, mods, name, str_values); 135 200 return ADS_ERR_OK(status); 136 201 } 137 202 return true; 138 139 }140 141 /*142 map a REG_DWORD to an ldap mod143 */144 static bool map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods,145 struct regval_blob *value)146 {147 char *str_value = NULL;148 ADS_STATUS status;149 150 if (regval_type(value) != REG_DWORD)151 return False;152 str_value = talloc_asprintf(ctx, "%d", *((uint32 *) regval_data_p(value)));153 if (!str_value) {154 return False;155 }156 status = ads_mod_str(ctx, mods, regval_name(value), str_value);157 return ADS_ERR_OK(status);158 }159 160 /*161 map a boolean REG_BINARY to an ldap mod162 */163 static bool map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,164 struct regval_blob *value)165 {166 char *str_value;167 ADS_STATUS status;168 169 if ((regval_type(value) != REG_BINARY) || (regval_size(value) != 1))170 return False;171 str_value = talloc_asprintf(ctx, "%s",172 *(regval_data_p(value)) ? "TRUE" : "FALSE");173 if (!str_value) {174 return False;175 }176 status = ads_mod_str(ctx, mods, regval_name(value), str_value);177 return ADS_ERR_OK(status);178 }179 180 /*181 map a REG_MULTI_SZ to an ldap mod182 */183 static bool map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,184 struct regval_blob *value)185 {186 char **str_values = NULL;187 size_t converted_size;188 smb_ucs2_t *cur_str = (smb_ucs2_t *) regval_data_p(value);189 uint32 size = 0, num_vals = 0, i=0;190 ADS_STATUS status;191 192 if (regval_type(value) != REG_MULTI_SZ)193 return False;194 195 while(cur_str && *cur_str && (size < regval_size(value))) {196 size += 2 * (strlen_w(cur_str) + 1);197 cur_str += strlen_w(cur_str) + 1;198 num_vals++;199 };200 201 if (num_vals) {202 str_values = TALLOC_ARRAY(ctx, char *, num_vals + 1);203 if (!str_values) {204 return False;205 }206 memset(str_values, '\0',207 (num_vals + 1) * sizeof(char *));208 209 cur_str = (smb_ucs2_t *) regval_data_p(value);210 for (i=0; i < num_vals; i++) {211 cur_str += pull_ucs2_talloc(ctx, &str_values[i],212 cur_str, &converted_size) ?213 converted_size : (size_t)-1;214 }215 216 status = ads_mod_strlist(ctx, mods, regval_name(value),217 (const char **) str_values);218 return ADS_ERR_OK(status);219 }220 return True;221 203 } 222 204 223 205 struct valmap_to_ads { 224 206 const char *valname; 225 bool (*fn)(TALLOC_CTX *, ADS_MODLIST *, struct regval_blob*);207 bool (*fn)(TALLOC_CTX *, ADS_MODLIST *, const char *, struct registry_value *); 226 208 }; 227 209 … … 230 212 */ 231 213 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods, 232 struct regval_blob*value)214 const char *name, struct registry_value *value) 233 215 { 234 216 const struct valmap_to_ads map[] = { … … 290 272 291 273 for (i=0; map[i].valname; i++) { 292 if ( StrCaseCmp(map[i].valname, regval_name(value)) == 0) {293 if (!map[i].fn(ctx, mods, value)) {294 DEBUG(5, ("Add of value %s to modlist failed\n", regval_name(value)));274 if (strcasecmp_m(map[i].valname, name) == 0) { 275 if (!map[i].fn(ctx, mods, name, value)) { 276 DEBUG(5, ("Add of value %s to modlist failed\n", name)); 295 277 } else { 296 DEBUG(7, ("Mapped value %s\n", regval_name(value)));278 DEBUG(7, ("Mapped value %s\n", name)); 297 279 } 298 299 280 } 300 281 } … … 312 293 struct spoolss_PrinterEnumValues *info; 313 294 uint32_t count; 314 uint32 i;295 uint32_t i; 315 296 struct policy_handle pol; 316 297 WERROR werr; … … 344 325 /* Have the data we need now, so start building */ 345 326 for (i=0; i < count; i++) { 346 struct regval_blob *v; 347 348 v = regval_compose(mem_ctx, info[i].value_name, 349 info[i].type, 350 info[i].data->data, 351 info[i].data->length); 352 if (v == NULL) { 353 return WERR_NOMEM; 354 } 355 356 map_regval_to_ads(mem_ctx, mods, v); 357 talloc_free(v); 327 struct registry_value v; 328 v.type = info[i].type; 329 v.data = *info[i].data; 330 331 map_regval_to_ads(mem_ctx, mods, info[i].value_name, &v); 358 332 } 359 333 } … … 369 343 } else { 370 344 for (i=0; i < count; i++) { 371 struct regval_blob *v; 372 373 v = regval_compose(mem_ctx, info[i].value_name, 374 info[i].type, 375 info[i].data->data, 376 info[i].data->length); 377 if (v == NULL) { 378 return WERR_NOMEM; 379 } 380 381 map_regval_to_ads(mem_ctx, mods, v); 382 talloc_free(v); 345 struct registry_value v; 346 v.type = info[i].type; 347 v.data = *info[i].data; 348 349 map_regval_to_ads(mem_ctx, mods, info[i].value_name, &v); 383 350 } 384 351 } -
vendor/current/source3/libads/ldap_schema.c
r740 r988 77 77 } 78 78 79 if (((*names) = TALLOC_ARRAY(mem_ctx, char *, *count)) == NULL) {79 if (((*names) = talloc_array(mem_ctx, char *, *count)) == NULL) { 80 80 status = ADS_ERROR(LDAP_NO_MEMORY); 81 81 goto out; 82 82 } 83 if (((*OIDs_out) = TALLOC_ARRAY(mem_ctx, char *, *count)) == NULL) {83 if (((*OIDs_out) = talloc_array(mem_ctx, char *, *count)) == NULL) { 84 84 status = ADS_ERROR(LDAP_NO_MEMORY); 85 85 goto out; … … 253 253 } 254 254 255 if ( (schema = TALLOC_P(mem_ctx, struct posix_schema)) == NULL ) {255 if ( (schema = talloc(mem_ctx, struct posix_schema)) == NULL ) { 256 256 TALLOC_FREE( ctx ); 257 257 return ADS_ERROR(LDAP_NO_MEMORY); -
vendor/current/source3/libads/ldap_utils.c
r746 r988 23 23 #include "includes.h" 24 24 #include "ads.h" 25 #include "lib/param/loadparm.h" 25 26 26 27 #ifdef HAVE_LDAP … … 36 37 char ***strings, 37 38 size_t *num_strings, 38 uint32 *first_usn,39 uint32_t *first_usn, 39 40 int *num_retries, 40 41 bool *more_values); … … 85 86 while (--count) { 86 87 87 if (NT_STATUS_EQUAL(ads_ntstatus(status), NT_STATUS_IO_TIMEOUT) && ads->config.ldap_page_size >= 250) { 88 if (NT_STATUS_EQUAL(ads_ntstatus(status), NT_STATUS_IO_TIMEOUT) && 89 ads->config.ldap_page_size >= (lp_ldap_page_size() / 4) && 90 lp_ldap_page_size() > 4) { 88 91 int new_page_size = (ads->config.ldap_page_size / 2); 89 92 DEBUG(1, ("Reducing LDAP page size from %d to %d due to IO_TIMEOUT\n", … … 169 172 170 173 ADS_STATUS ads_search_retry_dn_sd_flags(ADS_STRUCT *ads, LDAPMessage **res, 171 uint32 sd_flags,174 uint32_t sd_flags, 172 175 const char *dn, 173 176 const char **attrs) … … 214 217 ADS_STATUS status; 215 218 216 sid_string = sid_binstring_hex (sid);219 sid_string = sid_binstring_hex_talloc(talloc_tos(), sid); 217 220 if (sid_string == NULL) { 218 221 return ADS_ERROR(LDAP_NO_MEMORY); … … 220 223 221 224 if (!asprintf(&dn, "<SID=%s>", sid_string)) { 222 SAFE_FREE(sid_string);225 TALLOC_FREE(sid_string); 223 226 return ADS_ERROR(LDAP_NO_MEMORY); 224 227 } … … 227 230 "(objectclass=*)", attrs, res); 228 231 SAFE_FREE(dn); 229 SAFE_FREE(sid_string);232 TALLOC_FREE(sid_string); 230 233 return status; 231 234 } … … 242 245 { 243 246 ADS_STATUS status; 244 uint32 first_usn;247 uint32_t first_usn; 245 248 int num_retries = 0; 246 249 const char **attrs; … … 250 253 *strings = NULL; 251 254 252 attrs = TALLOC_ARRAY(mem_ctx, const char *, 3);255 attrs = talloc_array(mem_ctx, const char *, 3); 253 256 ADS_ERROR_HAVE_NO_MEMORY(attrs); 254 257 … … 296 299 char ***strings, 297 300 size_t *num_strings, 298 uint32 *first_usn,301 uint32_t *first_usn, 299 302 int *num_retries, 300 303 bool *more_values) … … 303 306 ADS_STATUS status; 304 307 int count; 305 uint32 current_usn;308 uint32_t current_usn; 306 309 307 310 DEBUG(10, ("Searching for attrs[0] = %s, attrs[1] = %s\n", attrs[0], attrs[1])); -
vendor/current/source3/libads/ndr.c
r740 r988 23 23 #include "ads.h" 24 24 #include "../librpc/gen_ndr/ndr_netlogon.h" 25 #include "librpc/ndr/util.h" 25 #include "../librpc/ndr/libndr.h" 26 #include "lib/param/loadparm.h" 26 27 27 28 static void ndr_print_ads_auth_flags(struct ndr_print *ndr, const char *name, uint32_t r) … … 37 38 ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "ADS_AUTH_SASL_SEAL", ADS_AUTH_SASL_SEAL, r); 38 39 ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "ADS_AUTH_SASL_FORCE", ADS_AUTH_SASL_FORCE, r); 40 ndr_print_bitmap_flag(ndr, sizeof(uint32_t), "ADS_AUTH_USER_CREDS", ADS_AUTH_USER_CREDS, r); 39 41 ndr->depth--; 40 42 } … … 50 52 ndr_print_string(ndr, "workgroup", r->server.workgroup); 51 53 ndr_print_string(ndr, "ldap_server", r->server.ldap_server); 52 ndr_print_bool(ndr, "foreign", r->server.foreign);53 54 ndr->depth--; 54 55 ndr_print_struct(ndr, name, "auth"); -
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 -
vendor/current/source3/libads/sasl_wrapping.c
r740 r988 46 46 ads->ldap.in.size = 4 + ads->ldap.in.min_wrapped; 47 47 ads->ldap.in.buf = talloc_array(ads->ldap.mem_ctx, 48 uint8 , ads->ldap.in.size);48 uint8_t, ads->ldap.in.size); 49 49 if (!ads->ldap.in.buf) { 50 50 return -1; … … 63 63 ads->ldap.in.buf = talloc_realloc(ads->ldap.mem_ctx, 64 64 ads->ldap.in.buf, 65 uint8 , ads->ldap.in.size);65 uint8_t, ads->ldap.in.size); 66 66 if (!ads->ldap.in.buf) { 67 67 return -1; … … 172 172 } 173 173 174 static ber_slen_t ads_saslwrap_prepare_outbuf(ADS_STRUCT *ads, uint32 len)174 static ber_slen_t ads_saslwrap_prepare_outbuf(ADS_STRUCT *ads, uint32_t len) 175 175 { 176 176 ads->ldap.out.ofs = 0; … … 178 178 ads->ldap.out.size = 4 + ads->ldap.out.sig_size + len; 179 179 ads->ldap.out.buf = talloc_array(ads->ldap.mem_ctx, 180 uint8 , ads->ldap.out.size);180 uint8_t, ads->ldap.out.size); 181 181 if (!ads->ldap.out.buf) { 182 182 return -1; … … 215 215 if (ret < 0) return ret; 216 216 217 status = ads->ldap.wrap_ops->wrap(ads, (uint8 *)buf, rlen);217 status = ads->ldap.wrap_ops->wrap(ads, (uint8_t *)buf, rlen); 218 218 if (!ADS_ERR_OK(status)) { 219 219 errno = EACCES; -
vendor/current/source3/libads/sitename_cache.c
r740 r988 80 80 ****************************************************************************/ 81 81 82 char *sitename_fetch( const char *realm)82 char *sitename_fetch(TALLOC_CTX *mem_ctx, const char *realm) 83 83 { 84 84 char *sitename = NULL; … … 96 96 key = sitename_key(query_realm); 97 97 98 ret = gencache_get( key, &sitename, &timeout );98 ret = gencache_get( key, mem_ctx, &sitename, &timeout ); 99 99 SAFE_FREE(key); 100 100 if ( !ret ) { … … 123 123 } 124 124 125 new_sitename = sitename_fetch( realm);125 new_sitename = sitename_fetch(talloc_tos(), realm); 126 126 127 127 if (sitename && new_sitename && !strequal(sitename, new_sitename)) { … … 131 131 ret = True; 132 132 } 133 SAFE_FREE(new_sitename);133 TALLOC_FREE(new_sitename); 134 134 return ret; 135 135 } -
vendor/current/source3/libads/sitename_cache.h
r740 r988 23 23 24 24 bool sitename_store(const char *realm, const char *sitename); 25 char *sitename_fetch( const char *realm);25 char *sitename_fetch(TALLOC_CTX *mem_ctx, const char *realm); 26 26 bool stored_sitename_changed(const char *realm, const char *sitename); 27 27 -
vendor/current/source3/libads/util.c
r740 r988 36 36 } 37 37 38 new_password = generate_random_str(talloc_tos(), DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH); 39 38 new_password = generate_random_password(talloc_tos(), 39 DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH, 40 DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH); 41 40 42 ret = kerberos_set_password(ads->auth.kdc_server, host_principal, password, host_principal, new_password, ads->auth.time_offset); 41 43
Note:
See TracChangeset
for help on using the changeset viewer.