static int prop_one (krb5_context context, HDB *db, hdb_entry *entry, void *v) { krb5_error_code ret; krb5_storage *sp; krb5_data data; struct slave *slave = (struct slave *)v; ret = hdb_entry2value (context, entry, &data); if (ret) return ret; ret = krb5_data_realloc (&data, data.length + 4); if (ret) { krb5_data_free (&data); return ret; } memmove ((char *)data.data + 4, data.data, data.length - 4); sp = krb5_storage_from_data(&data); if (sp == NULL) { krb5_data_free (&data); return ENOMEM; } krb5_store_int32(sp, ONE_PRINC); krb5_storage_free(sp); ret = krb5_write_priv_message (context, slave->ac, &slave->fd, &data); krb5_data_free (&data); return ret; }
static int dump_one (krb5_context context, HDB *db, hdb_entry_ex *entry, void *v) { krb5_error_code ret; krb5_storage *dump = (krb5_storage *)v; krb5_storage *sp; krb5_data data; ret = hdb_entry2value (context, &entry->entry, &data); if (ret) return ret; ret = krb5_data_realloc (&data, data.length + 4); if (ret) goto done; memmove ((char *)data.data + 4, data.data, data.length - 4); sp = krb5_storage_from_data(&data); if (sp == NULL) { ret = ENOMEM; goto done; } ret = krb5_store_uint32(sp, ONE_PRINC); krb5_storage_free(sp); if (ret == 0) ret = krb5_store_data(dump, data); done: krb5_data_free (&data); return ret; }
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_pac_add_buffer(krb5_context context, krb5_pac p, uint32_t type, const krb5_data *data) { krb5_error_code ret; void *ptr; size_t len, offset, header_end, old_end; uint32_t i; len = p->pac->numbuffers; ptr = realloc(p->pac, sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * len)); if (ptr == NULL) return krb5_enomem(context); p->pac = ptr; for (i = 0; i < len; i++) p->pac->buffers[i].offset_lo += PAC_INFO_BUFFER_SIZE; offset = p->data.length + PAC_INFO_BUFFER_SIZE; p->pac->buffers[len].type = type; p->pac->buffers[len].buffersize = data->length; p->pac->buffers[len].offset_lo = offset; p->pac->buffers[len].offset_hi = 0; old_end = p->data.length; len = p->data.length + data->length + PAC_INFO_BUFFER_SIZE; if (len < p->data.length) { krb5_set_error_message(context, EINVAL, "integer overrun"); return EINVAL; } /* align to PAC_ALIGNMENT */ len = ((len + PAC_ALIGNMENT - 1) / PAC_ALIGNMENT) * PAC_ALIGNMENT; ret = krb5_data_realloc(&p->data, len); if (ret) { krb5_set_error_message(context, ret, N_("malloc: out of memory", "")); return ret; } /* * make place for new PAC INFO BUFFER header */ header_end = PACTYPE_SIZE + (PAC_INFO_BUFFER_SIZE * p->pac->numbuffers); memmove((unsigned char *)p->data.data + header_end + PAC_INFO_BUFFER_SIZE, (unsigned char *)p->data.data + header_end , old_end - header_end); memset((unsigned char *)p->data.data + header_end, 0, PAC_INFO_BUFFER_SIZE); /* * copy in new data part */ memcpy((unsigned char *)p->data.data + offset, data->data, data->length); memset((unsigned char *)p->data.data + offset + data->length, 0, p->data.length - offset - data->length); p->pac->numbuffers += 1; return 0; }
static void change (krb5_auth_context auth_context, krb5_principal admin_principal, uint16_t version, int s, struct sockaddr *sa, int sa_size, krb5_data *in_data) { krb5_error_code ret; char *client = NULL, *admin = NULL; const char *pwd_reason; kadm5_config_params conf; void *kadm5_handle = NULL; krb5_principal principal = NULL; krb5_data *pwd_data = NULL; char *tmp; ChangePasswdDataMS chpw; memset (&conf, 0, sizeof(conf)); memset(&chpw, 0, sizeof(chpw)); if (version == KRB5_KPASSWD_VERS_CHANGEPW) { ret = krb5_copy_data(context, in_data, &pwd_data); if (ret) { krb5_warn (context, ret, "krb5_copy_data"); reply_priv (auth_context, s, sa, sa_size, KRB5_KPASSWD_MALFORMED, "out out memory copying password"); return; } principal = admin_principal; } else if (version == KRB5_KPASSWD_VERS_SETPW) { size_t len; ret = decode_ChangePasswdDataMS(in_data->data, in_data->length, &chpw, &len); if (ret) { krb5_warn (context, ret, "decode_ChangePasswdDataMS"); reply_priv (auth_context, s, sa, sa_size, KRB5_KPASSWD_MALFORMED, "malformed ChangePasswdData"); return; } ret = krb5_copy_data(context, &chpw.newpasswd, &pwd_data); if (ret) { krb5_warn (context, ret, "krb5_copy_data"); reply_priv (auth_context, s, sa, sa_size, KRB5_KPASSWD_MALFORMED, "out out memory copying password"); goto out; } if (chpw.targname == NULL && chpw.targrealm != NULL) { krb5_warn (context, ret, "kadm5_init_with_password_ctx"); reply_priv (auth_context, s, sa, sa_size, KRB5_KPASSWD_MALFORMED, "targrealm but not targname"); goto out; } if (chpw.targname) { krb5_principal_data princ; princ.name = *chpw.targname; princ.realm = *chpw.targrealm; if (princ.realm == NULL) { ret = krb5_get_default_realm(context, &princ.realm); if (ret) { krb5_warnx (context, "kadm5_init_with_password_ctx: " "failed to allocate realm"); reply_priv (auth_context, s, sa, sa_size, KRB5_KPASSWD_SOFTERROR, "failed to allocate realm"); goto out; } } ret = krb5_copy_principal(context, &princ, &principal); if (*chpw.targrealm == NULL) free(princ.realm); if (ret) { krb5_warn(context, ret, "krb5_copy_principal"); reply_priv(auth_context, s, sa, sa_size, KRB5_KPASSWD_HARDERROR, "failed to allocate principal"); goto out; } } else principal = admin_principal; } else { krb5_warnx (context, "kadm5_init_with_password_ctx: unknown proto"); reply_priv (auth_context, s, sa, sa_size, KRB5_KPASSWD_HARDERROR, "Unknown protocol used"); return; } ret = krb5_unparse_name (context, admin_principal, &admin); if (ret) { krb5_warn (context, ret, "unparse_name failed"); reply_priv (auth_context, s, sa, sa_size, KRB5_KPASSWD_HARDERROR, "out of memory error"); goto out; } conf.realm = principal->realm; conf.mask |= KADM5_CONFIG_REALM; ret = kadm5_init_with_password_ctx(context, admin, NULL, KADM5_ADMIN_SERVICE, &conf, 0, 0, &kadm5_handle); if (ret) { krb5_warn (context, ret, "kadm5_init_with_password_ctx"); reply_priv (auth_context, s, sa, sa_size, 2, "Internal error"); goto out; } ret = krb5_unparse_name(context, principal, &client); if (ret) { krb5_warn (context, ret, "unparse_name failed"); reply_priv (auth_context, s, sa, sa_size, KRB5_KPASSWD_HARDERROR, "out of memory error"); goto out; } /* * Check password quality if not changing as administrator */ if (krb5_principal_compare(context, admin_principal, principal) == TRUE) { pwd_reason = kadm5_check_password_quality (context, principal, pwd_data); if (pwd_reason != NULL ) { krb5_warnx (context, "%s didn't pass password quality check with error: %s", client, pwd_reason); reply_priv (auth_context, s, sa, sa_size, KRB5_KPASSWD_SOFTERROR, pwd_reason); goto out; } krb5_warnx (context, "Changing password for %s", client); } else { ret = _kadm5_acl_check_permission(kadm5_handle, KADM5_PRIV_CPW, principal); if (ret) { krb5_warn (context, ret, "Check ACL failed for %s for changing %s password", admin, client); reply_priv (auth_context, s, sa, sa_size, KRB5_KPASSWD_HARDERROR, "permission denied"); goto out; } krb5_warnx (context, "%s is changing password for %s", admin, client); } ret = krb5_data_realloc(pwd_data, pwd_data->length + 1); if (ret) { krb5_warn (context, ret, "malloc: out of memory"); reply_priv (auth_context, s, sa, sa_size, KRB5_KPASSWD_HARDERROR, "Internal error"); goto out; } tmp = pwd_data->data; tmp[pwd_data->length - 1] = '\0'; ret = kadm5_s_chpass_principal_cond (kadm5_handle, principal, tmp); krb5_free_data (context, pwd_data); pwd_data = NULL; if (ret) { const char *str = krb5_get_error_message(context, ret); krb5_warnx(context, "kadm5_s_chpass_principal_cond: %s", str); reply_priv (auth_context, s, sa, sa_size, KRB5_KPASSWD_SOFTERROR, str ? str : "Internal error"); krb5_free_error_message(context, str); goto out; } reply_priv (auth_context, s, sa, sa_size, KRB5_KPASSWD_SUCCESS, "Password changed"); out: free_ChangePasswdDataMS(&chpw); if (principal != admin_principal) krb5_free_principal(context, principal); if (admin) free(admin); if (client) free(client); if (pwd_data) krb5_free_data(context, pwd_data); if (kadm5_handle) kadm5_destroy (kadm5_handle); }