Exemple #1
0
static krb5_error_code
LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent,
		LDAPMessage * msg, LDAPMod *** pmods)
{
    krb5_error_code ret;
    krb5_boolean is_new_entry;
    char *tmp = NULL;
    LDAPMod **mods = NULL;
    hdb_entry_ex orig;
    unsigned long oflags, nflags;
    int i;

    krb5_boolean is_samba_account = FALSE;
    krb5_boolean is_account = FALSE;
    krb5_boolean is_heimdal_entry = FALSE;
    krb5_boolean is_heimdal_principal = FALSE;

    struct berval **vals;

    *pmods = NULL;

    if (msg != NULL) {

	ret = LDAP_message2entry(context, db, msg, 0, &orig);
	if (ret)
	    goto out;

	is_new_entry = FALSE;

	vals = ldap_get_values_len(HDB2LDAP(db), msg, "objectClass");
	if (vals) {
	    int num_objectclasses = ldap_count_values_len(vals);
	    for (i=0; i < num_objectclasses; i++) {
		if (bervalstrcmp(vals[i], "sambaSamAccount"))
		    is_samba_account = TRUE;
		else if (bervalstrcmp(vals[i], structural_object))
		    is_account = TRUE;
		else if (bervalstrcmp(vals[i], "krb5Principal"))
		    is_heimdal_principal = TRUE;
		else if (bervalstrcmp(vals[i], "krb5KDCEntry"))
		    is_heimdal_entry = TRUE;
	    }
	    ldap_value_free_len(vals);
	}

	/*
	 * If this is just a "account" entry and no other objectclass
	 * is hanging on this entry, it's really a new entry.
	 */
	if (is_samba_account == FALSE && is_heimdal_principal == FALSE &&
	    is_heimdal_entry == FALSE) {
	    if (is_account == TRUE) {
		is_new_entry = TRUE;
	    } else {
		ret = HDB_ERR_NOENTRY;
		goto out;
	    }
	}
    } else
	is_new_entry = TRUE;

    if (is_new_entry) {

	/* to make it perfectly obvious we're depending on
	 * orig being intiialized to zero */
	memset(&orig, 0, sizeof(orig));

	ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "top");
	if (ret)
	    goto out;

	/* account is the structural object class */
	if (is_account == FALSE) {
	    ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass",
			      structural_object);
	    is_account = TRUE;
	    if (ret)
		goto out;
	}

	ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "krb5Principal");
	is_heimdal_principal = TRUE;
	if (ret)
	    goto out;

	ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "krb5KDCEntry");
	is_heimdal_entry = TRUE;
	if (ret)
	    goto out;
    }

    if (is_new_entry ||
	krb5_principal_compare(context, ent->entry.principal, orig.entry.principal)
	== FALSE)
    {
	if (is_heimdal_principal || is_heimdal_entry) {

	    ret = krb5_unparse_name(context, ent->entry.principal, &tmp);
	    if (ret)
		goto out;

	    ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE,
			      "krb5PrincipalName", tmp);
	    if (ret) {
		free(tmp);
		goto out;
	    }
	    free(tmp);
	}

	if (is_account || is_samba_account) {
	    ret = krb5_unparse_name_short(context, ent->entry.principal, &tmp);
	    if (ret)
		goto out;
	    ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE, "uid", tmp);
	    if (ret) {
		free(tmp);
		goto out;
	    }
	    free(tmp);
	}
    }

    if (is_heimdal_entry && (ent->entry.kvno != orig.entry.kvno || is_new_entry)) {
	ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
			    "krb5KeyVersionNumber",
			    ent->entry.kvno);
	if (ret)
	    goto out;
    }

    if (is_heimdal_entry && ent->entry.valid_start) {
	if (orig.entry.valid_end == NULL
	    || (*(ent->entry.valid_start) != *(orig.entry.valid_start))) {
	    ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE,
					       "krb5ValidStart",
					       ent->entry.valid_start);
	    if (ret)
		goto out;
	}
    }

    if (ent->entry.valid_end) {
 	if (orig.entry.valid_end == NULL || (*(ent->entry.valid_end) != *(orig.entry.valid_end))) {
	    if (is_heimdal_entry) {
		ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE,
						   "krb5ValidEnd",
						   ent->entry.valid_end);
		if (ret)
		    goto out;
            }
	    if (is_samba_account) {
		ret = LDAP_addmod_integer(context, &mods,  LDAP_MOD_REPLACE,
					  "sambaKickoffTime",
					  *(ent->entry.valid_end));
		if (ret)
		    goto out;
	    }
   	}
    }

    if (ent->entry.pw_end) {
	if (orig.entry.pw_end == NULL || (*(ent->entry.pw_end) != *(orig.entry.pw_end))) {
	    if (is_heimdal_entry) {
		ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE,
						   "krb5PasswordEnd",
						   ent->entry.pw_end);
		if (ret)
		    goto out;
	    }

	    if (is_samba_account) {
		ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
					  "sambaPwdMustChange",
					  *(ent->entry.pw_end));
		if (ret)
		    goto out;
	    }
	}
    }


#if 0 /* we we have last_pw_change */
    if (is_samba_account && ent->entry.last_pw_change) {
	if (orig.entry.last_pw_change == NULL || (*(ent->entry.last_pw_change) != *(orig.entry.last_pw_change))) {
	    ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
				      "sambaPwdLastSet",
				      *(ent->entry.last_pw_change));
	    if (ret)
		goto out;
	}
    }
#endif

    if (is_heimdal_entry && ent->entry.max_life) {
	if (orig.entry.max_life == NULL
	    || (*(ent->entry.max_life) != *(orig.entry.max_life))) {

	    ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
				      "krb5MaxLife",
				      *(ent->entry.max_life));
	    if (ret)
		goto out;
	}
    }

    if (is_heimdal_entry && ent->entry.max_renew) {
	if (orig.entry.max_renew == NULL
	    || (*(ent->entry.max_renew) != *(orig.entry.max_renew))) {

	    ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
				      "krb5MaxRenew",
				      *(ent->entry.max_renew));
	    if (ret)
		goto out;
	}
    }

    oflags = HDBFlags2int(orig.entry.flags);
    nflags = HDBFlags2int(ent->entry.flags);

    if (is_heimdal_entry && oflags != nflags) {

	ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
				  "krb5KDCFlags",
				  nflags);
	if (ret)
	    goto out;
    }

    /* Remove keys if they exists, and then replace keys. */
    if (!is_new_entry && orig.entry.keys.len > 0) {
	vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5Key");
	if (vals) {
	    ldap_value_free_len(vals);

	    ret = LDAP_addmod(&mods, LDAP_MOD_DELETE, "krb5Key", NULL);
	    if (ret)
		goto out;
	}
    }

    for (i = 0; i < ent->entry.keys.len; i++) {

	if (is_samba_account
	    && ent->entry.keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) {
	    char *ntHexPassword;
	    char *nt;
	    time_t now = time(NULL);

	    /* the key might have been 'sealed', but samba passwords
	       are clear in the directory */
	    ret = hdb_unseal_key(context, db, &ent->entry.keys.val[i]);
	    if (ret)
		goto out;

	    nt = ent->entry.keys.val[i].key.keyvalue.data;
	    /* store in ntPassword, not krb5key */
	    ret = hex_encode(nt, 16, &ntHexPassword);
	    if (ret < 0) {
		ret = ENOMEM;
		krb5_set_error_message(context, ret, "hdb-ldap: failed to "
				      "hex encode key");
		goto out;
	    }
	    ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE, "sambaNTPassword",
			      ntHexPassword);
	    free(ntHexPassword);
	    if (ret)
		goto out;
	    ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
				      "sambaPwdLastSet", now);
	    if (ret)
		goto out;

	    /* have to kill the LM passwod if it exists */
	    vals = ldap_get_values_len(HDB2LDAP(db), msg, "sambaLMPassword");
	    if (vals) {
		ldap_value_free_len(vals);
		ret = LDAP_addmod(&mods, LDAP_MOD_DELETE,
				  "sambaLMPassword", NULL);
		if (ret)
		    goto out;
	    }

	} else if (is_heimdal_entry) {
	    unsigned char *buf;
	    size_t len, buf_size;

	    ASN1_MALLOC_ENCODE(Key, buf, buf_size, &ent->entry.keys.val[i], &len, ret);
	    if (ret)
		goto out;
	    if(buf_size != len)
		krb5_abortx(context, "internal error in ASN.1 encoder");

	    /* addmod_len _owns_ the key, doesn't need to copy it */
	    ret = LDAP_addmod_len(&mods, LDAP_MOD_ADD, "krb5Key", buf, len);
	    if (ret)
		goto out;
	}
    }

    if (ent->entry.etypes) {
	int add_krb5EncryptionType = 0;

	/*
	 * Only add/modify krb5EncryptionType if it's a new heimdal
	 * entry or krb5EncryptionType already exists on the entry.
	 */

	if (!is_new_entry) {
	    vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5EncryptionType");
	    if (vals) {
		ldap_value_free_len(vals);
		ret = LDAP_addmod(&mods, LDAP_MOD_DELETE, "krb5EncryptionType",
				  NULL);
		if (ret)
		    goto out;
		add_krb5EncryptionType = 1;
	    }
	} else if (is_heimdal_entry)
	    add_krb5EncryptionType = 1;

	if (add_krb5EncryptionType) {
	    for (i = 0; i < ent->entry.etypes->len; i++) {
		if (is_samba_account &&
		    ent->entry.keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5)
		{
		    ;
		} else if (is_heimdal_entry) {
		    ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_ADD,
					      "krb5EncryptionType",
					      ent->entry.etypes->val[i]);
		    if (ret)
			goto out;
		}
	    }
	}
    }

    /* for clarity */
    ret = 0;

 out:

    if (ret == 0)
	*pmods = mods;
    else if (mods != NULL) {
	ldap_mods_free(mods, 1);
	*pmods = NULL;
    }

    if (msg)
	hdb_free_entry(context, &orig);

    return ret;
}
Exemple #2
0
static krb5_error_code
entry2string_int (krb5_context context, krb5_storage *sp, hdb_entry *ent)
{
    char *p;
    int i;
    krb5_error_code ret;

    /* --- principal */
    ret = krb5_unparse_name(context, ent->principal, &p);
    if(ret)
	return ret;
    append_string(context, sp, "%s ", p);
    free(p);
    /* --- kvno */
    append_string(context, sp, "%d", ent->kvno);
    /* --- keys */
    for(i = 0; i < ent->keys.len; i++){
	/* --- mkvno, keytype */
	if(ent->keys.val[i].mkvno)
	    append_string(context, sp, ":%d:%d:", 
			  *ent->keys.val[i].mkvno, 
			  ent->keys.val[i].key.keytype);
	else
	    append_string(context, sp, "::%d:", 
			  ent->keys.val[i].key.keytype);
	/* --- keydata */
	append_hex(context, sp, &ent->keys.val[i].key.keyvalue);
	append_string(context, sp, ":");
	/* --- salt */
	if(ent->keys.val[i].salt){
	    append_string(context, sp, "%u/", ent->keys.val[i].salt->type);
	    append_hex(context, sp, &ent->keys.val[i].salt->salt);
	}else
	    append_string(context, sp, "-");
    }
    append_string(context, sp, " ");
    /* --- created by */
    append_event(context, sp, &ent->created_by);
    /* --- modified by */
    append_event(context, sp, ent->modified_by);

    /* --- valid start */
    if(ent->valid_start)
	append_string(context, sp, "%s ", time2str(*ent->valid_start));
    else
	append_string(context, sp, "- ");

    /* --- valid end */
    if(ent->valid_end)
	append_string(context, sp, "%s ", time2str(*ent->valid_end));
    else
	append_string(context, sp, "- ");
    
    /* --- password ends */
    if(ent->pw_end)
	append_string(context, sp, "%s ", time2str(*ent->pw_end));
    else
	append_string(context, sp, "- ");

    /* --- max life */
    if(ent->max_life)
	append_string(context, sp, "%d ", *ent->max_life);
    else
	append_string(context, sp, "- ");

    /* --- max renewable life */
    if(ent->max_renew)
	append_string(context, sp, "%d ", *ent->max_renew);
    else
	append_string(context, sp, "- ");
    
    /* --- flags */
    append_string(context, sp, "%d ", HDBFlags2int(ent->flags));

    /* --- generation number */
    if(ent->generation) {
	append_string(context, sp, "%s:%d:%d", time2str(ent->generation->time),
		      ent->generation->usec,
		      ent->generation->gen);
    } else
	append_string(context, sp, "-");
    
    return 0;
}
Exemple #3
0
static krb5_error_code
entry2string_int (krb5_context context, krb5_storage *sp, hdb_entry *ent)
{
    char *p;
    size_t i;
    krb5_error_code ret;

    /* --- principal */
    ret = krb5_unparse_name(context, ent->principal, &p);
    if(ret)
	return ret;
    append_string(context, sp, "%s ", p);
    free(p);
    /* --- kvno */
    append_string(context, sp, "%d", ent->kvno);
    /* --- keys */
    for(i = 0; i < ent->keys.len; i++){
	/* --- mkvno, keytype */
	if(ent->keys.val[i].mkvno)
	    append_string(context, sp, ":%d:%d:",
			  *ent->keys.val[i].mkvno,
			  ent->keys.val[i].key.keytype);
	else
	    append_string(context, sp, "::%d:",
			  ent->keys.val[i].key.keytype);
	/* --- keydata */
	append_hex(context, sp, &ent->keys.val[i].key.keyvalue);
	append_string(context, sp, ":");
	/* --- salt */
	if(ent->keys.val[i].salt){
	    append_string(context, sp, "%u/", ent->keys.val[i].salt->type);
	    append_hex(context, sp, &ent->keys.val[i].salt->salt);
	}else
	    append_string(context, sp, "-");
    }
    append_string(context, sp, " ");
    /* --- created by */
    append_event(context, sp, &ent->created_by);
    /* --- modified by */
    append_event(context, sp, ent->modified_by);

    /* --- valid start */
    if(ent->valid_start)
	append_string(context, sp, "%s ", time2str(*ent->valid_start));
    else
	append_string(context, sp, "- ");

    /* --- valid end */
    if(ent->valid_end)
	append_string(context, sp, "%s ", time2str(*ent->valid_end));
    else
	append_string(context, sp, "- ");

    /* --- password ends */
    if(ent->pw_end)
	append_string(context, sp, "%s ", time2str(*ent->pw_end));
    else
	append_string(context, sp, "- ");

    /* --- max life */
    if(ent->max_life)
	append_string(context, sp, "%d ", *ent->max_life);
    else
	append_string(context, sp, "- ");

    /* --- max renewable life */
    if(ent->max_renew)
	append_string(context, sp, "%d ", *ent->max_renew);
    else
	append_string(context, sp, "- ");

    /* --- flags */
    append_string(context, sp, "%d ", HDBFlags2int(ent->flags));

    /* --- generation number */
    if(ent->generation) {
	append_string(context, sp, "%s:%d:%d ", time2str(ent->generation->time),
		      ent->generation->usec,
		      ent->generation->gen);
    } else
	append_string(context, sp, "- ");

    /* --- extensions */
    if(ent->extensions && ent->extensions->len > 0) {
	for(i = 0; i < ent->extensions->len; i++) {
	    void *d;
	    size_t size, sz = 0;

	    ASN1_MALLOC_ENCODE(HDB_extension, d, size,
			       &ent->extensions->val[i], &sz, ret);
	    if (ret) {
		krb5_clear_error_message(context);
		return ret;
	    }
	    if(size != sz)
		krb5_abortx(context, "internal asn.1 encoder error");

	    if (hex_encode(d, size, &p) < 0) {
		free(d);
		krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
		return ENOMEM;
	    }

	    free(d);
	    append_string(context, sp, "%s%s", p,
			  ent->extensions->len - 1 != i ? ":" : "");
	    free(p);
	}
    } else
	append_string(context, sp, "-");


    return 0;
}
Exemple #4
0
static void
print_entry(kadm5_server_context *server_context,
	    uint32_t ver,
	    time_t timestamp,
	    enum kadm_ops op,
	    uint32_t len,
	    krb5_storage *sp,
	    void *ctx)
{
    char t[256];
    int32_t mask;
    hdb_entry ent;
    krb5_principal source;
    char *name1, *name2;
    krb5_data data;
    krb5_context scontext = server_context->context;

    off_t end = krb5_storage_seek(sp, 0, SEEK_CUR) + len;

    krb5_error_code ret;

    strftime(t, sizeof(t), "%Y-%m-%d %H:%M:%S", localtime(&timestamp));

    if((int)op < (int)kadm_get || (int)op > (int)kadm_nop) {
	printf("unknown op: %d\n", op);
	krb5_storage_seek(sp, end, SEEK_SET);
	return;
    }

    printf ("%s: ver = %u, timestamp = %s, len = %u\n",
	    op_names[op], ver, t, len);
    switch(op) {
    case kadm_delete:
	krb5_ret_principal(sp, &source);
	krb5_unparse_name(scontext, source, &name1);
	printf("    %s\n", name1);
	free(name1);
	krb5_free_principal(scontext, source);
	break;
    case kadm_rename:
	ret = krb5_data_alloc(&data, len);
	if (ret)
	    krb5_err (scontext, 1, ret, "kadm_rename: data alloc: %d", len);
	krb5_ret_principal(sp, &source);
	krb5_storage_read(sp, data.data, data.length);
	hdb_value2entry(scontext, &data, &ent);
	krb5_unparse_name(scontext, source, &name1);
	krb5_unparse_name(scontext, ent.principal, &name2);
	printf("    %s -> %s\n", name1, name2);
	free(name1);
	free(name2);
	krb5_free_principal(scontext, source);
	free_hdb_entry(&ent);
	break;
    case kadm_create:
	ret = krb5_data_alloc(&data, len);
	if (ret)
	    krb5_err (scontext, 1, ret, "kadm_create: data alloc: %d", len);
	krb5_storage_read(sp, data.data, data.length);
	ret = hdb_value2entry(scontext, &data, &ent);
	if(ret)
	    abort();
	mask = ~0;
	goto foo;
    case kadm_modify:
	ret = krb5_data_alloc(&data, len);
	if (ret)
	    krb5_err (scontext, 1, ret, "kadm_modify: data alloc: %d", len);
	krb5_ret_int32(sp, &mask);
	krb5_storage_read(sp, data.data, data.length);
	ret = hdb_value2entry(scontext, &data, &ent);
	if(ret)
	    abort();
    foo:
	if(ent.principal /* mask & KADM5_PRINCIPAL */) {
	    krb5_unparse_name(scontext, ent.principal, &name1);
	    printf("    principal = %s\n", name1);
	    free(name1);
	}
	if(mask & KADM5_PRINC_EXPIRE_TIME) {
	    if(ent.valid_end == NULL) {
		strlcpy(t, "never", sizeof(t));
	    } else {
		strftime(t, sizeof(t), "%Y-%m-%d %H:%M:%S",
			 localtime(ent.valid_end));
	    }
	    printf("    expires = %s\n", t);
	}
	if(mask & KADM5_PW_EXPIRATION) {
	    if(ent.pw_end == NULL) {
		strlcpy(t, "never", sizeof(t));
	    } else {
		strftime(t, sizeof(t), "%Y-%m-%d %H:%M:%S",
			 localtime(ent.pw_end));
	    }
	    printf("    password exp = %s\n", t);
	}
	if(mask & KADM5_LAST_PWD_CHANGE) {
	}
	if(mask & KADM5_ATTRIBUTES) {
	    unparse_flags(HDBFlags2int(ent.flags),
			  asn1_HDBFlags_units(), t, sizeof(t));
	    printf("    attributes = %s\n", t);
	}
	if(mask & KADM5_MAX_LIFE) {
	    if(ent.max_life == NULL)
		strlcpy(t, "for ever", sizeof(t));
	    else
		unparse_time(*ent.max_life, t, sizeof(t));
	    printf("    max life = %s\n", t);
	}
	if(mask & KADM5_MAX_RLIFE) {
	    if(ent.max_renew == NULL)
		strlcpy(t, "for ever", sizeof(t));
	    else
		unparse_time(*ent.max_renew, t, sizeof(t));
	    printf("    max rlife = %s\n", t);
	}
	if(mask & KADM5_MOD_TIME) {
	    printf("    mod time\n");
	}
	if(mask & KADM5_MOD_NAME) {
	    printf("    mod name\n");
	}
	if(mask & KADM5_KVNO) {
	    printf("    kvno = %d\n", ent.kvno);
	}
	if(mask & KADM5_MKVNO) {
	    printf("    mkvno\n");
	}
	if(mask & KADM5_AUX_ATTRIBUTES) {
	    printf("    aux attributes\n");
	}
	if(mask & KADM5_POLICY) {
	    printf("    policy\n");
	}
	if(mask & KADM5_POLICY_CLR) {
	    printf("    mod time\n");
	}
	if(mask & KADM5_LAST_SUCCESS) {
	    printf("    last success\n");
	}
	if(mask & KADM5_LAST_FAILED) {
	    printf("    last failed\n");
	}
	if(mask & KADM5_FAIL_AUTH_COUNT) {
	    printf("    fail auth count\n");
	}
	if(mask & KADM5_KEY_DATA) {
	    printf("    key data\n");
	}
	if(mask & KADM5_TL_DATA) {
	    printf("    tl data\n");
	}
	free_hdb_entry(&ent);
	break;
    case kadm_nop :
	break;
    default:
	abort();
    }
    krb5_storage_seek(sp, end, SEEK_SET);
}