Changeset 988 for vendor/current/source4/kdc/pac-glue.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source4/kdc/pac-glue.c
r740 r988 27 27 #include "auth/auth.h" 28 28 #include "auth/auth_sam_reply.h" 29 #include "kdc/kdc-glue.h" 29 #include "system/kerberos.h" 30 #include "auth/kerberos/kerberos.h" 31 #include "kdc/samba_kdc.h" 32 #include "kdc/pac-glue.h" 30 33 #include "param/param.h" 31 34 #include "librpc/gen_ndr/ndr_krb5pac.h" 35 #include "libcli/security/security.h" 36 #include "dsdb/samdb/samdb.h" 37 #include "auth/kerberos/pac_utils.h" 32 38 33 39 static … … 51 57 52 58 pac_info.logon_info.info = talloc_zero(mem_ctx, struct PAC_LOGON_INFO); 53 if (! mem_ctx) {59 if (!pac_info.logon_info.info) { 54 60 return NT_STATUS_NO_MEMORY; 55 61 } … … 72 78 krb5_error_code samba_make_krb5_pac(krb5_context context, 73 79 DATA_BLOB *pac_blob, 80 DATA_BLOB *deleg_blob, 74 81 krb5_pac *pac) 75 82 { 76 83 krb5_data pac_data; 84 krb5_data deleg_data; 77 85 krb5_error_code ret; 78 86 … … 82 90 } 83 91 84 ret = krb5_data_copy(&pac_data, pac_blob->data, pac_blob->length); 92 ret = krb5_copy_data_contents(&pac_data, 93 pac_blob->data, 94 pac_blob->length); 85 95 if (ret != 0) { 86 96 return ret; 87 97 } 88 98 99 ZERO_STRUCT(deleg_data); 100 if (deleg_blob) { 101 ret = krb5_copy_data_contents(&deleg_data, 102 deleg_blob->data, 103 deleg_blob->length); 104 if (ret != 0) { 105 kerberos_free_data_contents(context, &pac_data); 106 return ret; 107 } 108 } 109 89 110 ret = krb5_pac_init(context, pac); 90 111 if (ret != 0) { 91 krb5_data_free(&pac_data); 112 kerberos_free_data_contents(context, &pac_data); 113 kerberos_free_data_contents(context, &deleg_data); 92 114 return ret; 93 115 } 94 116 95 117 ret = krb5_pac_add_buffer(context, *pac, PAC_TYPE_LOGON_INFO, &pac_data); 96 k rb5_data_free(&pac_data);118 kerberos_free_data_contents(context, &pac_data); 97 119 if (ret != 0) { 120 kerberos_free_data_contents(context, &deleg_data); 98 121 return ret; 99 122 } 100 123 124 if (deleg_blob) { 125 ret = krb5_pac_add_buffer(context, *pac, 126 PAC_TYPE_CONSTRAINED_DELEGATION, 127 &deleg_data); 128 kerberos_free_data_contents(context, &deleg_data); 129 if (ret != 0) { 130 return ret; 131 } 132 } 133 101 134 return ret; 102 135 } 103 136 104 bool samba_princ_needs_pac(struct hdb_entry_ex *princ) 105 { 106 107 struct samba_kdc_entry *p = talloc_get_type(princ->ctx, struct samba_kdc_entry); 137 bool samba_princ_needs_pac(struct samba_kdc_entry *skdc_entry) 138 { 139 108 140 uint32_t userAccountControl; 109 141 110 111 142 /* The service account may be set not to want the PAC */ 112 userAccountControl = ldb_msg_find_attr_as_uint( p->msg, "userAccountControl", 0);143 userAccountControl = ldb_msg_find_attr_as_uint(skdc_entry->msg, "userAccountControl", 0); 113 144 if (userAccountControl & UF_NO_AUTH_DATA_REQUIRED) { 114 145 return false; … … 118 149 } 119 150 120 /* Was the krbtgt an RODC (and we are not) */ 121 bool samba_krbtgt_was_untrusted_rodc(struct hdb_entry_ex *princ) 122 { 123 124 struct samba_kdc_entry *p = talloc_get_type(princ->ctx, struct samba_kdc_entry); 125 int rodc_krbtgt_number; 126 127 /* Determine if this was printed by an RODC */ 151 /* Was the krbtgt in this DB (ie, should we check the incoming signature) and was it an RODC */ 152 int samba_krbtgt_is_in_db(struct samba_kdc_entry *p, 153 bool *is_in_db, 154 bool *is_untrusted) 155 { 156 NTSTATUS status; 157 int rodc_krbtgt_number, trust_direction; 158 uint32_t rid; 159 160 TALLOC_CTX *mem_ctx = talloc_new(NULL); 161 if (!mem_ctx) { 162 return ENOMEM; 163 } 164 165 trust_direction = ldb_msg_find_attr_as_int(p->msg, "trustDirection", 0); 166 167 if (trust_direction != 0) { 168 /* Domain trust - we cannot check the sig, but we trust it for a correct PAC 169 170 This is exactly where we should flag for SID 171 validation when we do inter-foreest trusts 172 */ 173 talloc_free(mem_ctx); 174 *is_untrusted = false; 175 *is_in_db = false; 176 return 0; 177 } 178 179 /* The lack of password controls etc applies to krbtgt by 180 * virtue of being that particular RID */ 181 status = dom_sid_split_rid(NULL, samdb_result_dom_sid(mem_ctx, p->msg, "objectSid"), NULL, &rid); 182 183 if (!NT_STATUS_IS_OK(status)) { 184 talloc_free(mem_ctx); 185 return EINVAL; 186 } 187 128 188 rodc_krbtgt_number = ldb_msg_find_attr_as_int(p->msg, "msDS-SecondaryKrbTgtNumber", -1); 129 if (rodc_krbtgt_number == -1) { 130 return false; 131 } else if (rodc_krbtgt_number != p->kdc_db_ctx->my_krbtgt_number) { 132 return true; 133 } 134 135 return false; 189 190 if (p->kdc_db_ctx->my_krbtgt_number == 0) { 191 if (rid == DOMAIN_RID_KRBTGT) { 192 *is_untrusted = false; 193 *is_in_db = true; 194 talloc_free(mem_ctx); 195 return 0; 196 } else if (rodc_krbtgt_number != -1) { 197 *is_in_db = true; 198 *is_untrusted = true; 199 talloc_free(mem_ctx); 200 return 0; 201 } 202 } else if ((rid != DOMAIN_RID_KRBTGT) && (rodc_krbtgt_number == p->kdc_db_ctx->my_krbtgt_number)) { 203 talloc_free(mem_ctx); 204 *is_untrusted = false; 205 *is_in_db = true; 206 return 0; 207 } else if (rid == DOMAIN_RID_KRBTGT) { 208 /* krbtgt viewed from an RODC */ 209 talloc_free(mem_ctx); 210 *is_untrusted = false; 211 *is_in_db = false; 212 return 0; 213 } 214 215 /* Another RODC */ 216 talloc_free(mem_ctx); 217 *is_untrusted = true; 218 *is_in_db = false; 219 return 0; 136 220 } 137 221 138 222 NTSTATUS samba_kdc_get_pac_blob(TALLOC_CTX *mem_ctx, 139 struct hdb_entry_ex *client,223 struct samba_kdc_entry *p, 140 224 DATA_BLOB **_pac_blob) 141 225 { 142 struct samba_kdc_entry *p = talloc_get_type(client->ctx, struct samba_kdc_entry);143 226 struct auth_user_info_dc *user_info_dc; 144 227 DATA_BLOB *pac_blob; … … 146 229 147 230 /* The user account may be set not to want the PAC */ 148 if ( ! samba_princ_needs_pac( client)) {231 if ( ! samba_princ_needs_pac(p)) { 149 232 *_pac_blob = NULL; 150 233 return NT_STATUS_OK; … … 183 266 NTSTATUS samba_kdc_update_pac_blob(TALLOC_CTX *mem_ctx, 184 267 krb5_context context, 185 krb5_pac *pac, DATA_BLOB *pac_blob) 268 const krb5_pac pac, DATA_BLOB *pac_blob, 269 struct PAC_SIGNATURE_DATA *pac_srv_sig, 270 struct PAC_SIGNATURE_DATA *pac_kdc_sig) 186 271 { 187 272 struct auth_user_info_dc *user_info_dc; … … 189 274 NTSTATUS nt_status; 190 275 191 ret = kerberos_pac_to_user_info_dc(mem_ctx, *pac,192 context, &user_info_dc, NULL, NULL);276 ret = kerberos_pac_to_user_info_dc(mem_ctx, pac, 277 context, &user_info_dc, pac_srv_sig, pac_kdc_sig); 193 278 if (ret) { 194 279 return NT_STATUS_UNSUCCESSFUL; … … 201 286 } 202 287 203 /* this function allocates 'data' using malloc. 204 * The caller is responsible for freeing it */ 205 void samba_kdc_build_edata_reply(NTSTATUS nt_status, DATA_BLOB *e_data) 206 { 207 PA_DATA pa; 208 unsigned char *buf; 209 size_t len; 210 krb5_error_code ret = 0; 211 212 if (!e_data) 213 return; 214 215 pa.padata_type = KRB5_PADATA_PW_SALT; 216 pa.padata_value.length = 12; 217 pa.padata_value.data = malloc(pa.padata_value.length); 218 if (!pa.padata_value.data) { 219 e_data->length = 0; 220 e_data->data = NULL; 221 return; 222 } 223 224 SIVAL(pa.padata_value.data, 0, NT_STATUS_V(nt_status)); 225 SIVAL(pa.padata_value.data, 4, 0); 226 SIVAL(pa.padata_value.data, 8, 1); 227 228 ASN1_MALLOC_ENCODE(PA_DATA, buf, len, &pa, &len, ret); 229 free(pa.padata_value.data); 230 231 e_data->data = buf; 232 e_data->length = len; 233 234 return; 288 NTSTATUS samba_kdc_update_delegation_info_blob(TALLOC_CTX *mem_ctx, 289 krb5_context context, 290 const krb5_pac pac, 291 const krb5_principal server_principal, 292 const krb5_principal proxy_principal, 293 DATA_BLOB *new_blob) 294 { 295 krb5_data old_data; 296 DATA_BLOB old_blob; 297 krb5_error_code ret; 298 NTSTATUS nt_status; 299 enum ndr_err_code ndr_err; 300 union PAC_INFO info; 301 struct PAC_CONSTRAINED_DELEGATION _d; 302 struct PAC_CONSTRAINED_DELEGATION *d = NULL; 303 char *server = NULL; 304 char *proxy = NULL; 305 uint32_t i; 306 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); 307 308 if (tmp_ctx == NULL) { 309 return NT_STATUS_NO_MEMORY; 310 } 311 312 ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_CONSTRAINED_DELEGATION, &old_data); 313 if (ret == ENOENT) { 314 ZERO_STRUCT(old_data); 315 } else if (ret) { 316 talloc_free(tmp_ctx); 317 return NT_STATUS_UNSUCCESSFUL; 318 } 319 320 old_blob.length = old_data.length; 321 old_blob.data = (uint8_t *)old_data.data; 322 323 ZERO_STRUCT(info); 324 if (old_blob.length > 0) { 325 ndr_err = ndr_pull_union_blob(&old_blob, mem_ctx, 326 &info, PAC_TYPE_CONSTRAINED_DELEGATION, 327 (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO); 328 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 329 kerberos_free_data_contents(context, &old_data); 330 nt_status = ndr_map_error2ntstatus(ndr_err); 331 DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status))); 332 talloc_free(tmp_ctx); 333 return nt_status; 334 } 335 } else { 336 ZERO_STRUCT(_d); 337 info.constrained_delegation.info = &_d; 338 } 339 kerberos_free_data_contents(context, &old_data); 340 341 ret = krb5_unparse_name(context, server_principal, &server); 342 if (ret) { 343 talloc_free(tmp_ctx); 344 return NT_STATUS_INTERNAL_ERROR; 345 } 346 347 ret = krb5_unparse_name_flags(context, proxy_principal, 348 KRB5_PRINCIPAL_UNPARSE_NO_REALM, &proxy); 349 if (ret) { 350 SAFE_FREE(server); 351 talloc_free(tmp_ctx); 352 return NT_STATUS_INTERNAL_ERROR; 353 } 354 355 d = info.constrained_delegation.info; 356 i = d->num_transited_services; 357 d->proxy_target.string = server; 358 d->transited_services = talloc_realloc(mem_ctx, d->transited_services, 359 struct lsa_String, i + 1); 360 d->transited_services[i].string = proxy; 361 d->num_transited_services = i + 1; 362 363 ndr_err = ndr_push_union_blob(new_blob, mem_ctx, 364 &info, PAC_TYPE_CONSTRAINED_DELEGATION, 365 (ndr_push_flags_fn_t)ndr_push_PAC_INFO); 366 SAFE_FREE(server); 367 SAFE_FREE(proxy); 368 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 369 kerberos_free_data_contents(context, &old_data); 370 nt_status = ndr_map_error2ntstatus(ndr_err); 371 DEBUG(0,("can't parse the PAC LOGON_INFO: %s\n", nt_errstr(nt_status))); 372 talloc_free(tmp_ctx); 373 return nt_status; 374 } 375 376 talloc_free(tmp_ctx); 377 return NT_STATUS_OK; 235 378 } 236 379 … … 241 384 242 385 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_MUST_CHANGE)) 243 ret = KRB5KDC_ERR_KEY_EXP IRED;386 ret = KRB5KDC_ERR_KEY_EXP; 244 387 else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_PASSWORD_EXPIRED)) 245 ret = KRB5KDC_ERR_KEY_EXP IRED;388 ret = KRB5KDC_ERR_KEY_EXP; 246 389 else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCOUNT_EXPIRED)) 247 390 ret = KRB5KDC_ERR_CLIENT_REVOKED; … … 287 430 return nt_status; 288 431 } 289
Note:
See TracChangeset
for help on using the changeset viewer.