Esempio n. 1
0
kadm5_ret_t
_kadm5_bump_pw_expire(kadm5_server_context *context,
		      hdb_entry *ent)
{
    if (ent->pw_end != NULL) {
	time_t life;

	life = krb5_config_get_time_default(context->context,
					    NULL,
					    365 * 24 * 60 * 60,
					    "kadmin",
					    "password_lifetime",
					    NULL);

	*(ent->pw_end) = time(NULL) + life;
    }
    return 0;
}
Esempio n. 2
0
krb5_error_code
krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
{
    krb5_kdc_configuration *c;

    c = calloc(1, sizeof(*c));
    if (c == NULL) {
	krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
	return ENOMEM;
    }

    c->require_preauth = TRUE;
    c->kdc_warn_pwexpire = 0;
    c->encode_as_rep_as_tgs_rep = FALSE;
    c->tgt_use_strongest_session_key = FALSE;
    c->preauth_use_strongest_session_key = FALSE;
    c->svc_use_strongest_session_key = FALSE;
    c->use_strongest_server_key = TRUE;
    c->check_ticket_addresses = TRUE;
    c->allow_null_ticket_addresses = TRUE;
    c->allow_anonymous = FALSE;
    c->trpolicy = TRPOLICY_ALWAYS_CHECK;
    c->enable_pkinit = FALSE;
    c->pkinit_princ_in_cert = TRUE;
    c->pkinit_require_binding = TRUE;
    c->db = NULL;
    c->num_db = 0;
    c->logf = NULL;

    c->require_preauth =
	krb5_config_get_bool_default(context, NULL,
				     c->require_preauth,
				     "kdc", "require-preauth", NULL);
#ifdef DIGEST
    c->enable_digest =
	krb5_config_get_bool_default(context, NULL,
				     FALSE,
				     "kdc", "enable-digest", NULL);

    {
	const char *digests;

	digests = krb5_config_get_string(context, NULL,
					 "kdc",
					 "digests_allowed", NULL);
	if (digests == NULL)
	    digests = "ntlm-v2";
	c->digests_allowed = parse_flags(digests,_kdc_digestunits, 0);
	if (c->digests_allowed == -1) {
	    kdc_log(context, c, 0,
		    "unparsable digest units (%s), turning off digest",
		    digests);
	    c->enable_digest = 0;
	} else if (c->digests_allowed == 0) {
	    kdc_log(context, c, 0,
		    "no digest enable, turning digest off",
		    digests);
	    c->enable_digest = 0;
	}
    }
#endif

#ifdef KX509
    c->enable_kx509 =
	krb5_config_get_bool_default(context, NULL,
				     FALSE,
				     "kdc", "enable-kx509", NULL);

    if (c->enable_kx509) {
	c->kx509_template =
	    krb5_config_get_string(context, NULL,
				   "kdc", "kx509_template", NULL);
	c->kx509_ca =
	    krb5_config_get_string(context, NULL,
				   "kdc", "kx509_ca", NULL);
	if (c->kx509_ca == NULL || c->kx509_template == NULL) {
	    kdc_log(context, c, 0,
		    "missing kx509 configuration, turning off");
	    c->enable_kx509 = FALSE;
	}
    }
#endif

    c->tgt_use_strongest_session_key =
	krb5_config_get_bool_default(context, NULL,
				     c->tgt_use_strongest_session_key,
				     "kdc",
				     "tgt-use-strongest-session-key", NULL);
    c->preauth_use_strongest_session_key =
	krb5_config_get_bool_default(context, NULL,
				     c->preauth_use_strongest_session_key,
				     "kdc",
				     "preauth-use-strongest-session-key", NULL);
    c->svc_use_strongest_session_key =
	krb5_config_get_bool_default(context, NULL,
				     c->svc_use_strongest_session_key,
				     "kdc",
				     "svc-use-strongest-session-key", NULL);
    c->use_strongest_server_key =
	krb5_config_get_bool_default(context, NULL,
				     c->use_strongest_server_key,
				     "kdc",
				     "use-strongest-server-key", NULL);

    c->check_ticket_addresses =
	krb5_config_get_bool_default(context, NULL,
				     c->check_ticket_addresses,
				     "kdc",
				     "check-ticket-addresses", NULL);
    c->allow_null_ticket_addresses =
	krb5_config_get_bool_default(context, NULL,
				     c->allow_null_ticket_addresses,
				     "kdc",
				     "allow-null-ticket-addresses", NULL);

    c->allow_anonymous =
	krb5_config_get_bool_default(context, NULL,
				     c->allow_anonymous,
				     "kdc",
				     "allow-anonymous", NULL);

    c->max_datagram_reply_length =
	krb5_config_get_int_default(context,
				    NULL,
				    1400,
				    "kdc",
				    "max-kdc-datagram-reply-length",
				    NULL);

    {
	const char *trpolicy_str;

	trpolicy_str =
	    krb5_config_get_string_default(context, NULL, "DEFAULT", "kdc",
					   "transited-policy", NULL);
	if(strcasecmp(trpolicy_str, "always-check") == 0) {
	    c->trpolicy = TRPOLICY_ALWAYS_CHECK;
	} else if(strcasecmp(trpolicy_str, "allow-per-principal") == 0) {
	    c->trpolicy = TRPOLICY_ALLOW_PER_PRINCIPAL;
	} else if(strcasecmp(trpolicy_str, "always-honour-request") == 0) {
	    c->trpolicy = TRPOLICY_ALWAYS_HONOUR_REQUEST;
	} else if(strcasecmp(trpolicy_str, "DEFAULT") == 0) {
	    /* default */
	} else {
	    kdc_log(context, c, 0,
		    "unknown transited-policy: %s, "
		    "reverting to default (always-check)",
		    trpolicy_str);
	}
    }

    c->encode_as_rep_as_tgs_rep =
	krb5_config_get_bool_default(context, NULL,
				     c->encode_as_rep_as_tgs_rep,
				     "kdc",
				     "encode_as_rep_as_tgs_rep", NULL);

    c->kdc_warn_pwexpire =
	krb5_config_get_time_default (context, NULL,
				      c->kdc_warn_pwexpire,
				      "kdc", "kdc_warn_pwexpire", NULL);


    c->enable_pkinit =
	krb5_config_get_bool_default(context,
				     NULL,
				     c->enable_pkinit,
				     "kdc",
				     "enable-pkinit",
				     NULL);


    c->pkinit_kdc_identity =
	krb5_config_get_string(context, NULL,
			       "kdc", "pkinit_identity", NULL);
    c->pkinit_kdc_anchors =
	krb5_config_get_string(context, NULL,
			       "kdc", "pkinit_anchors", NULL);
    c->pkinit_kdc_cert_pool =
	krb5_config_get_strings(context, NULL,
				"kdc", "pkinit_pool", NULL);
    c->pkinit_kdc_revoke =
	krb5_config_get_strings(context, NULL,
				"kdc", "pkinit_revoke", NULL);
    c->pkinit_kdc_ocsp_file =
	krb5_config_get_string(context, NULL,
			       "kdc", "pkinit_kdc_ocsp", NULL);
    c->pkinit_kdc_friendly_name =
	krb5_config_get_string(context, NULL,
			       "kdc", "pkinit_kdc_friendly_name", NULL);
    c->pkinit_princ_in_cert =
	krb5_config_get_bool_default(context, NULL,
				     c->pkinit_princ_in_cert,
				     "kdc",
				     "pkinit_principal_in_certificate",
				     NULL);
    c->pkinit_require_binding =
	krb5_config_get_bool_default(context, NULL,
				     c->pkinit_require_binding,
				     "kdc",
				     "pkinit_win2k_require_binding",
				     NULL);
    c->pkinit_dh_min_bits =
	krb5_config_get_int_default(context, NULL,
				    0,
				    "kdc", "pkinit_dh_min_bits", NULL);

    *config = c;

    return 0;
}
Esempio n. 3
0
/*
 * Construct an hdb_entry from a directory entry.
 */
static krb5_error_code
LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg,
		   hdb_entry_ex * ent)
{
    char *unparsed_name = NULL, *dn = NULL, *ntPasswordIN = NULL;
    char *samba_acct_flags = NULL;
    struct berval **keys;
    struct berval **vals;
    int tmp, tmp_time, i, ret, have_arcfour = 0;

    memset(ent, 0, sizeof(*ent));
    ent->entry.flags = int2HDBFlags(0);

    ret = LDAP_get_string_value(db, msg, "krb5PrincipalName", &unparsed_name);
    if (ret == 0) {
	ret = krb5_parse_name(context, unparsed_name, &ent->entry.principal);
	if (ret)
	    goto out;
    } else {
	ret = LDAP_get_string_value(db, msg, "uid",
				    &unparsed_name);
	if (ret == 0) {
	    ret = krb5_parse_name(context, unparsed_name, &ent->entry.principal);
	    if (ret)
		goto out;
	} else {
	    krb5_set_error_message(context, HDB_ERR_NOENTRY,
				   "hdb-ldap: ldap entry missing"
				  "principal name");
	    return HDB_ERR_NOENTRY;
	}
    }

    {
	int integer;
	ret = LDAP_get_integer_value(db, msg, "krb5KeyVersionNumber",
				     &integer);
	if (ret)
	    ent->entry.kvno = 0;
	else
	    ent->entry.kvno = integer;
    }

    keys = ldap_get_values_len(HDB2LDAP(db), msg, "krb5Key");
    if (keys != NULL) {
	int i;
	size_t l;

	ent->entry.keys.len = ldap_count_values_len(keys);
	ent->entry.keys.val = (Key *) calloc(ent->entry.keys.len, sizeof(Key));
	if (ent->entry.keys.val == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret, "calloc: out of memory");
	    goto out;
	}
	for (i = 0; i < ent->entry.keys.len; i++) {
	    decode_Key((unsigned char *) keys[i]->bv_val,
		       (size_t) keys[i]->bv_len, &ent->entry.keys.val[i], &l);
	}
	ber_bvecfree(keys);
    } else {
#if 1
	/*
	 * This violates the ASN1 but it allows a principal to
	 * be related to a general directory entry without creating
	 * the keys. Hopefully it's OK.
	 */
	ent->entry.keys.len = 0;
	ent->entry.keys.val = NULL;
#else
	ret = HDB_ERR_NOENTRY;
	goto out;
#endif
    }

    vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5EncryptionType");
    if (vals != NULL) {
	int i;

	ent->entry.etypes = malloc(sizeof(*(ent->entry.etypes)));
	if (ent->entry.etypes == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret,"malloc: out of memory");
	    goto out;
	}
	ent->entry.etypes->len = ldap_count_values_len(vals);
	ent->entry.etypes->val = calloc(ent->entry.etypes->len, sizeof(int));
	if (ent->entry.etypes->val == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret, "malloc: out of memory");
	    ent->entry.etypes->len = 0;
	    goto out;
	}
	for (i = 0; i < ent->entry.etypes->len; i++) {
	    char *buf;

	    buf = malloc(vals[i]->bv_len + 1);
	    if (buf == NULL) {
		ret = ENOMEM;
		krb5_set_error_message(context, ret, "malloc: out of memory");
		goto out;
	    }
	    memcpy(buf, vals[i]->bv_val, vals[i]->bv_len);
	    buf[vals[i]->bv_len] = '\0';
	    ent->entry.etypes->val[i] = atoi(buf);
	    free(buf);
	}
	ldap_value_free_len(vals);
    }

    for (i = 0; i < ent->entry.keys.len; i++) {
	if (ent->entry.keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) {
	    have_arcfour = 1;
	    break;
	}
    }

    /* manually construct the NT (type 23) key */
    ret = LDAP_get_string_value(db, msg, "sambaNTPassword", &ntPasswordIN);
    if (ret == 0 && have_arcfour == 0) {
	unsigned *etypes;
	Key *keys;
	int i;

	keys = realloc(ent->entry.keys.val,
		       (ent->entry.keys.len + 1) * sizeof(ent->entry.keys.val[0]));
	if (keys == NULL) {
	    free(ntPasswordIN);
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret, "malloc: out of memory");
	    goto out;
	}
	ent->entry.keys.val = keys;
	memset(&ent->entry.keys.val[ent->entry.keys.len], 0, sizeof(Key));
	ent->entry.keys.val[ent->entry.keys.len].key.keytype = ETYPE_ARCFOUR_HMAC_MD5;
	ret = krb5_data_alloc (&ent->entry.keys.val[ent->entry.keys.len].key.keyvalue, 16);
	if (ret) {
	    krb5_set_error_message(context, ret, "malloc: out of memory");
	    free(ntPasswordIN);
	    ret = ENOMEM;
	    goto out;
	}
	ret = hex_decode(ntPasswordIN,
			 ent->entry.keys.val[ent->entry.keys.len].key.keyvalue.data, 16);
	ent->entry.keys.len++;

	if (ent->entry.etypes == NULL) {
	    ent->entry.etypes = malloc(sizeof(*(ent->entry.etypes)));
	    if (ent->entry.etypes == NULL) {
		ret = ENOMEM;
		krb5_set_error_message(context, ret, "malloc: out of memory");
		goto out;
	    }
	    ent->entry.etypes->val = NULL;
	    ent->entry.etypes->len = 0;
	}

	for (i = 0; i < ent->entry.etypes->len; i++)
	    if (ent->entry.etypes->val[i] == ETYPE_ARCFOUR_HMAC_MD5)
		break;
	/* If there is no ARCFOUR enctype, add one */
	if (i == ent->entry.etypes->len) {
	    etypes = realloc(ent->entry.etypes->val,
			     (ent->entry.etypes->len + 1) *
			     sizeof(ent->entry.etypes->val[0]));
	    if (etypes == NULL) {
		ret = ENOMEM;
		krb5_set_error_message(context, ret, "malloc: out of memory");
		goto out;			
	    }
	    ent->entry.etypes->val = etypes;
	    ent->entry.etypes->val[ent->entry.etypes->len] =
		ETYPE_ARCFOUR_HMAC_MD5;
	    ent->entry.etypes->len++;
	}
    }

    ret = LDAP_get_generalized_time_value(db, msg, "createTimestamp",
					  &ent->entry.created_by.time);
    if (ret)
	ent->entry.created_by.time = time(NULL);

    ent->entry.created_by.principal = NULL;

    ret = LDAP_get_string_value(db, msg, "creatorsName", &dn);
    if (ret == 0) {
	if (LDAP_dn2principal(context, db, dn, &ent->entry.created_by.principal)
	    != 0) {
	    ent->entry.created_by.principal = NULL;
	}
	free(dn);
    }

    ent->entry.modified_by = (Event *) malloc(sizeof(Event));
    if (ent->entry.modified_by == NULL) {
	ret = ENOMEM;
	krb5_set_error_message(context, ret, "malloc: out of memory");
	goto out;
    }
    ret = LDAP_get_generalized_time_value(db, msg, "modifyTimestamp",
					  &ent->entry.modified_by->time);
    if (ret == 0) {
	ret = LDAP_get_string_value(db, msg, "modifiersName", &dn);
	if (LDAP_dn2principal(context, db, dn, &ent->entry.modified_by->principal))
	    ent->entry.modified_by->principal = NULL;
	free(dn);
    } else {
	free(ent->entry.modified_by);
	ent->entry.modified_by = NULL;
    }

    ent->entry.valid_start = malloc(sizeof(*ent->entry.valid_start));
    if (ent->entry.valid_start == NULL) {
	ret = ENOMEM;
	krb5_set_error_message(context, ret, "malloc: out of memory");
	goto out;
    }
    ret = LDAP_get_generalized_time_value(db, msg, "krb5ValidStart",
					  ent->entry.valid_start);
    if (ret) {
	/* OPTIONAL */
	free(ent->entry.valid_start);
	ent->entry.valid_start = NULL;
    }

    ent->entry.valid_end = malloc(sizeof(*ent->entry.valid_end));
    if (ent->entry.valid_end == NULL) {
	ret = ENOMEM;
	krb5_set_error_message(context, ret, "malloc: out of memory");
	goto out;
    }
    ret = LDAP_get_generalized_time_value(db, msg, "krb5ValidEnd",
					  ent->entry.valid_end);
    if (ret) {
	/* OPTIONAL */
	free(ent->entry.valid_end);
	ent->entry.valid_end = NULL;
    }

    ret = LDAP_get_integer_value(db, msg, "sambaKickoffTime", &tmp_time);
    if (ret == 0) {
 	if (ent->entry.valid_end == NULL) {
 	    ent->entry.valid_end = malloc(sizeof(*ent->entry.valid_end));
 	    if (ent->entry.valid_end == NULL) {
 		ret = ENOMEM;
 		krb5_set_error_message(context, ret, "malloc: out of memory");
 		goto out;
 	    }
 	}
 	*ent->entry.valid_end = tmp_time;
    }

    ent->entry.pw_end = malloc(sizeof(*ent->entry.pw_end));
    if (ent->entry.pw_end == NULL) {
	ret = ENOMEM;
	krb5_set_error_message(context, ret, "malloc: out of memory");
	goto out;
    }
    ret = LDAP_get_generalized_time_value(db, msg, "krb5PasswordEnd",
					  ent->entry.pw_end);
    if (ret) {
	/* OPTIONAL */
	free(ent->entry.pw_end);
	ent->entry.pw_end = NULL;
    }

    ret = LDAP_get_integer_value(db, msg, "sambaPwdLastSet", &tmp_time);
    if (ret == 0) {
	time_t delta;

	if (ent->entry.pw_end == NULL) {
            ent->entry.pw_end = malloc(sizeof(*ent->entry.pw_end));
            if (ent->entry.pw_end == NULL) {
                ret = ENOMEM;
                krb5_set_error_message(context, ret, "malloc: out of memory");
                goto out;
            }
        }

	delta = krb5_config_get_time_default(context, NULL, 
					     365 * 24 * 60 * 60,
					     "kadmin",
					     "password_lifetime",
					     NULL);
        *ent->entry.pw_end = tmp_time + delta;
    }

    ret = LDAP_get_integer_value(db, msg, "sambaPwdMustChange", &tmp_time);
    if (ret == 0) {
	if (ent->entry.pw_end == NULL) {
	    ent->entry.pw_end = malloc(sizeof(*ent->entry.pw_end));
	    if (ent->entry.pw_end == NULL) {
		ret = ENOMEM;
		krb5_set_error_message(context, ret, "malloc: out of memory");
		goto out;
	    }
	}
	*ent->entry.pw_end = tmp_time;
    }

    /* OPTIONAL */
    ret = LDAP_get_integer_value(db, msg, "sambaPwdLastSet", &tmp_time);
    if (ret == 0)
	hdb_entry_set_pw_change_time(context, &ent->entry, tmp_time);

    {
	int max_life;

	ent->entry.max_life = malloc(sizeof(*ent->entry.max_life));
	if (ent->entry.max_life == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret, "malloc: out of memory");
	    goto out;
	}
	ret = LDAP_get_integer_value(db, msg, "krb5MaxLife", &max_life);
	if (ret) {
	    free(ent->entry.max_life);
	    ent->entry.max_life = NULL;
	} else
	    *ent->entry.max_life = max_life;
    }

    {
	int max_renew;

	ent->entry.max_renew = malloc(sizeof(*ent->entry.max_renew));
	if (ent->entry.max_renew == NULL) {
	    ret = ENOMEM;
	    krb5_set_error_message(context, ret, "malloc: out of memory");
	    goto out;
	}
	ret = LDAP_get_integer_value(db, msg, "krb5MaxRenew", &max_renew);
	if (ret) {
	    free(ent->entry.max_renew);
	    ent->entry.max_renew = NULL;
	} else
	    *ent->entry.max_renew = max_renew;
    }

    ret = LDAP_get_integer_value(db, msg, "krb5KDCFlags", &tmp);
    if (ret)
	tmp = 0;

    ent->entry.flags = int2HDBFlags(tmp);

    /* Try and find Samba flags to put into the mix */
    ret = LDAP_get_string_value(db, msg, "sambaAcctFlags", &samba_acct_flags);
    if (ret == 0) {
	/* parse the [UXW...] string:
	
	   'N'    No password	
	   'D'    Disabled	
	   'H'    Homedir required	
	   'T'    Temp account.	
	   'U'    User account (normal) 	
	   'M'    MNS logon user account - what is this ? 	
	   'W'    Workstation account	
	   'S'    Server account 	
	   'L'    Locked account	
	   'X'    No Xpiry on password 	
	   'I'    Interdomain trust account	
	
	*/	
	
	int i;
	int flags_len = strlen(samba_acct_flags);

	if (flags_len < 2)
	    goto out2;

	if (samba_acct_flags[0] != '['
	    || samba_acct_flags[flags_len - 1] != ']')
	    goto out2;

	/* Allow forwarding */
	if (samba_forwardable)
	    ent->entry.flags.forwardable = TRUE;

	for (i=0; i < flags_len; i++) {
	    switch (samba_acct_flags[i]) {
	    case ' ':
	    case '[':
	    case ']':
		break;
	    case 'N':
		/* how to handle no password in kerberos? */
		break;
	    case 'D':
		ent->entry.flags.invalid = TRUE;
		break;
	    case 'H':
		break;
	    case 'T':
		/* temp duplicate */
		ent->entry.flags.invalid = TRUE;
		break;
	    case 'U':
		ent->entry.flags.client = TRUE;
		break;
	    case 'M':
		break;
	    case 'W':
	    case 'S':
		ent->entry.flags.server = TRUE;
		ent->entry.flags.client = TRUE;
		break;
	    case 'L':
		ent->entry.flags.invalid = TRUE;
		break;
	    case 'X':
		if (ent->entry.pw_end) {
		    free(ent->entry.pw_end);
		    ent->entry.pw_end = NULL;
		}
		break;
	    case 'I':
		ent->entry.flags.server = TRUE;
		ent->entry.flags.client = TRUE;
		break;
	    }
	}
    out2:
	free(samba_acct_flags);
    }

    ret = 0;

out:
    if (unparsed_name)
	free(unparsed_name);

    if (ret)
	hdb_free_entry(context, ent);

    return ret;
}