📄 kerberos5.c
字号:
unsigned int n = 0; ETYPE_INFO pa; unsigned char *buf; size_t len; pa.len = client->keys.len; if(pa.len > UINT_MAX/sizeof(*pa.val)) return ERANGE; pa.val = malloc(pa.len * sizeof(*pa.val)); if(pa.val == NULL) return ENOMEM; memset(pa.val, 0, pa.len * sizeof(*pa.val)); for(i = 0; i < client->keys.len; i++) { for (j = 0; j < n; j++) if (pa.val[j].etype == client->keys.val[i].key.keytype) goto skip1; for(j = 0; j < etypes_len; j++) { if(client->keys.val[i].key.keytype == etypes[j]) { if (krb5_enctype_valid(context, etypes[j]) != 0) continue; if (!older_enctype(etypes[j])) continue; if (n >= pa.len) krb5_abortx(context, "internal error: n >= p.len"); if((ret = make_etype_info_entry(context, &pa.val[n++], &client->keys.val[i])) != 0) { free_ETYPE_INFO(&pa); return ret; } break; } } skip1:; } for(i = 0; i < client->keys.len; i++) { /* already added? */ for(j = 0; j < etypes_len; j++) { if(client->keys.val[i].key.keytype == etypes[j]) goto skip2; } if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0) continue; if (!older_enctype(etypes[j])) continue; if (n >= pa.len) krb5_abortx(context, "internal error: n >= p.len"); if((ret = make_etype_info_entry(context, &pa.val[n++], &client->keys.val[i])) != 0) { free_ETYPE_INFO(&pa); return ret; } skip2:; } if(n < pa.len) { /* stripped out dups, newer enctypes, and not valid enctypes */ pa.len = n; } ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret); free_ETYPE_INFO(&pa); if(ret) return ret; ret = realloc_method_data(md); if(ret) { free(buf); return ret; } md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO; md->val[md->len - 1].padata_value.length = len; md->val[md->len - 1].padata_value.data = buf; return 0;}/* * */extern int _krb5_AES_string_to_default_iterator;static krb5_error_codemake_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key){ ent->etype = key->key.keytype; if(key->salt) { ALLOC(ent->salt); if (ent->salt == NULL) return ENOMEM; *ent->salt = malloc(key->salt->salt.length + 1); if (*ent->salt == NULL) { free(ent->salt); ent->salt = NULL; return ENOMEM; } memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length); (*ent->salt)[key->salt->salt.length] = '\0'; } else ent->salt = NULL; ent->s2kparams = NULL; switch (key->key.keytype) { case ETYPE_AES128_CTS_HMAC_SHA1_96: case ETYPE_AES256_CTS_HMAC_SHA1_96: ALLOC(ent->s2kparams); if (ent->s2kparams == NULL) return ENOMEM; ent->s2kparams->length = 4; ent->s2kparams->data = malloc(ent->s2kparams->length); if (ent->s2kparams->data == NULL) { free(ent->s2kparams); ent->s2kparams = NULL; return ENOMEM; } _krb5_put_int(ent->s2kparams->data, _krb5_AES_string_to_default_iterator, ent->s2kparams->length); break; case ETYPE_DES_CBC_CRC: case ETYPE_DES_CBC_MD4: case ETYPE_DES_CBC_MD5: /* Check if this was a AFS3 salted key */ if(key->salt && key->salt->type == hdb_afs3_salt){ ALLOC(ent->s2kparams); if (ent->s2kparams == NULL) return ENOMEM; ent->s2kparams->length = 1; ent->s2kparams->data = malloc(ent->s2kparams->length); if (ent->s2kparams->data == NULL) { free(ent->s2kparams); ent->s2kparams = NULL; return ENOMEM; } _krb5_put_int(ent->s2kparams->data, 1, ent->s2kparams->length); } break; default: break; } return 0;}/* * Return an ETYPE-INFO2. Enctypes are storted the same way as in the * database (client supported enctypes first, then the unsupported * enctypes). */static krb5_error_codeget_pa_etype_info2(krb5_context context, krb5_kdc_configuration *config, METHOD_DATA *md, hdb_entry *client, ENCTYPE *etypes, unsigned int etypes_len){ krb5_error_code ret = 0; int i, j; unsigned int n = 0; ETYPE_INFO2 pa; unsigned char *buf; size_t len; pa.len = client->keys.len; if(pa.len > UINT_MAX/sizeof(*pa.val)) return ERANGE; pa.val = malloc(pa.len * sizeof(*pa.val)); if(pa.val == NULL) return ENOMEM; memset(pa.val, 0, pa.len * sizeof(*pa.val)); for(i = 0; i < client->keys.len; i++) { for (j = 0; j < n; j++) if (pa.val[j].etype == client->keys.val[i].key.keytype) goto skip1; for(j = 0; j < etypes_len; j++) { if(client->keys.val[i].key.keytype == etypes[j]) { if (krb5_enctype_valid(context, etypes[j]) != 0) continue; if (n >= pa.len) krb5_abortx(context, "internal error: n >= p.len"); if((ret = make_etype_info2_entry(&pa.val[n++], &client->keys.val[i])) != 0) { free_ETYPE_INFO2(&pa); return ret; } break; } } skip1:; } /* send enctypes that the client doesn't know about too */ for(i = 0; i < client->keys.len; i++) { /* already added? */ for(j = 0; j < etypes_len; j++) { if(client->keys.val[i].key.keytype == etypes[j]) goto skip2; } if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0) continue; if (n >= pa.len) krb5_abortx(context, "internal error: n >= p.len"); if((ret = make_etype_info2_entry(&pa.val[n++], &client->keys.val[i])) != 0) { free_ETYPE_INFO2(&pa); return ret; } skip2:; } if(n < pa.len) { /* stripped out dups, and not valid enctypes */ pa.len = n; } ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret); free_ETYPE_INFO2(&pa); if(ret) return ret; ret = realloc_method_data(md); if(ret) { free(buf); return ret; } md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2; md->val[md->len - 1].padata_value.length = len; md->val[md->len - 1].padata_value.data = buf; return 0;}/* * */static voidlog_as_req(krb5_context context, krb5_kdc_configuration *config, krb5_enctype cetype, krb5_enctype setype, const KDC_REQ_BODY *b){ krb5_error_code ret; struct rk_strpool *p = NULL; char *str; int i; for (i = 0; i < b->etype.len; i++) { ret = krb5_enctype_to_string(context, b->etype.val[i], &str); if (ret == 0) { p = rk_strpoolprintf(p, "%s", str); free(str); } else p = rk_strpoolprintf(p, "%d", b->etype.val[i]); if (p && i + 1 < b->etype.len) p = rk_strpoolprintf(p, ", "); if (p == NULL) { kdc_log(context, config, 0, "out of memory"); return; } } if (p == NULL) p = rk_strpoolprintf(p, "no encryption types"); str = rk_strpoolcollect(p); kdc_log(context, config, 0, "Client supported enctypes: %s", str); free(str); { char *cet; char *set; ret = krb5_enctype_to_string(context, cetype, &cet); if(ret == 0) { ret = krb5_enctype_to_string(context, setype, &set); if (ret == 0) { kdc_log(context, config, 5, "Using %s/%s", cet, set); free(set); } free(cet); } if (ret != 0) kdc_log(context, config, 5, "Using e-types %d/%d", cetype, setype); } { char fixedstr[128]; unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(), fixedstr, sizeof(fixedstr)); if(*fixedstr) kdc_log(context, config, 2, "Requested flags: %s", fixedstr); }}/* * verify the flags on `client' and `server', returning 0 * if they are OK and generating an error messages and returning * and error code otherwise. */krb5_error_code_kdc_check_flags(krb5_context context, krb5_kdc_configuration *config, hdb_entry_ex *client_ex, const char *client_name, hdb_entry_ex *server_ex, const char *server_name, krb5_boolean is_as_req){ if(client_ex != NULL) { hdb_entry *client = &client_ex->entry; /* check client */ if (client->flags.invalid) { kdc_log(context, config, 0, "Client (%s) has invalid bit set", client_name); return KRB5KDC_ERR_POLICY; } if(!client->flags.client){ kdc_log(context, config, 0, "Principal may not act as client -- %s", client_name); return KRB5KDC_ERR_POLICY; } if (client->valid_start && *client->valid_start > kdc_time) { char starttime_str[100]; krb5_format_time(context, *client->valid_start, starttime_str, sizeof(starttime_str), TRUE); kdc_log(context, config, 0, "Client not yet valid until %s -- %s", starttime_str, client_name); return KRB5KDC_ERR_CLIENT_NOTYET; } if (client->valid_end && *client->valid_end < kdc_time) { char endtime_str[100]; krb5_format_time(context, *client->valid_end, endtime_str, sizeof(endtime_str), TRUE); kdc_log(context, config, 0, "Client expired at %s -- %s", endtime_str, client_name); return KRB5KDC_ERR_NAME_EXP; } if (client->pw_end && *client->pw_end < kdc_time && (server_ex == NULL || !server_ex->entry.flags.change_pw)) { char pwend_str[100]; krb5_format_time(context, *client->pw_end, pwend_str, sizeof(pwend_str), TRUE); kdc_log(context, config, 0, "Client's key has expired at %s -- %s", pwend_str, client_name); return KRB5KDC_ERR_KEY_EXPIRED; } } /* check server */ if (server_ex != NULL) { hdb_entry *server = &server_ex->entry; if (server->flags.invalid) { kdc_log(context, config, 0, "Server has invalid flag set -- %s", server_name); return KRB5KDC_ERR_POLICY; } if(!server->flags.server){ kdc_log(context, config, 0, "Principal may not act as server -- %s", server_name); return KRB5KDC_ERR_POLICY; } if(!is_as_req && server->flags.initial) { kdc_log(context, config, 0, "AS-REQ is required for server -- %s", server_name); return KRB5KDC_ERR_POLICY; } if (server->valid_start && *server->valid_start > kdc_time) { char starttime_str[100]; krb5_format_time(context, *server->valid_start, starttime_str, sizeof(starttime_str), TRUE); kdc_log(context, config, 0, "Server not yet valid until %s -- %s", starttime_str, server_name); return KRB5KDC_ERR_SERVICE_NOTYET; } if (server->valid_end && *server->valid_end < kdc_time) { char endtime_str[100]; krb5_format_time(context, *server->valid_end, endtime_str, sizeof(endtime_str), TRUE); kdc_log(context, config, 0, "Server expired at %s -- %s", endtime_str, server_name); return KRB5KDC_ERR_SERVICE_EXP; } if (server->pw_end && *server->pw_end < kdc_time) { char pwend_str[100]; krb5_format_time(context, *server->pw_end, pwend_str, sizeof(pwend_str), TRUE); kdc_log(context, config, 0, "Server's key has expired at -- %s", pwend_str, server_name); return KRB5KDC_ERR_KEY_EXPIRED; } } return 0;}/* * Return TRUE if `from' is part of `addresses' taking into consideration * the configuration variables that tells us how strict we should be about * these checks */krb5_boolean_kdc_check_addresses(krb5_context context, krb5_kdc_configuration *config, HostAddresses *addresses, const struct sockaddr *from){ krb5_error_code ret; krb5_address addr; krb5_boolean result; krb5_boolean only_netbios = TRUE; int i; if(config->check_ticket_addresses == 0) return TRUE; if(addresses == NULL) return config->allow_null_ticket_addresses; for (i = 0; i < addresses->len; ++i) { if (addresses->val[i].addr_type != KRB5_ADDRESS_NETBIOS) { only_netbios = FALSE; } } /* Windows sends it's netbios name, which I can only assume is * used for the 'allowed workstations' check. This is painful, * but we still want to check IP addresses if they happen to be * present. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -