Exemplo n.º 1
0
static krb5_error_code
krb5_validate_ldap_context(krb5_context context,
                           krb5_ldap_context *ldap_context)
{
    krb5_error_code             st=0;
    unsigned char               *password=NULL;

    if (ldap_context->bind_dn == NULL) {
        st = EINVAL;
        krb5_set_error_message(context, st, _("LDAP bind dn value missing "));
        goto err_out;
    }

    if (ldap_context->bind_pwd == NULL && ldap_context->service_password_file == NULL) {
        st = EINVAL;
        krb5_set_error_message(context, st,
                               _("LDAP bind password value missing "));
        goto err_out;
    }

    if (ldap_context->bind_pwd == NULL && ldap_context->service_password_file !=
            NULL && ldap_context->service_cert_path == NULL) {
        if ((st=krb5_ldap_readpassword(context, ldap_context, &password)) != 0) {
            prepend_err_str(context, _("Error reading password from stash: "),
                            st, st);
            goto err_out;
        }

        /* Check if the returned 'password' is actually the path of a certificate */
        if (!strncmp("{FILE}", (char *)password, 6)) {
            /* 'password' format: <path>\0<password> */
            ldap_context->service_cert_path = strdup((char *)password + strlen("{FILE}"));
            if (password[strlen((char *)password) + 1] == '\0')
                ldap_context->service_cert_pass = NULL;
            else
                ldap_context->service_cert_pass = strdup((char *)password +
                                                  strlen((char *)password) + 1);
            free(password);
        } else {
            ldap_context->bind_pwd = (char *)password;
            if (ldap_context->bind_pwd == NULL) {
                st = EINVAL;
                krb5_set_error_message(context, st,
                                       _("Error reading password from stash"));
                goto err_out;
            }
        }
    }

    /* NULL password not allowed */
    if (ldap_context->bind_pwd != NULL && strlen(ldap_context->bind_pwd) == 0) {
        st = EINVAL;
        krb5_set_error_message(context, st,
                               _("Service password length is zero"));
        goto err_out;
    }

err_out:
    return st;
}
Exemplo n.º 2
0
krb5_error_code
krb5_read_tkt_policy(krb5_context context, krb5_ldap_context *ldap_context,
                     krb5_db_entry *entries, char *policy)
{
    krb5_error_code             st=0;
    unsigned int                mask=0, omask=0;
    int                         tkt_mask=(KDB_MAX_LIFE_ATTR | KDB_MAX_RLIFE_ATTR | KDB_TKT_FLAGS_ATTR);
    krb5_ldap_policy_params     *tktpoldnparam=NULL;

    if ((st=krb5_get_attributes_mask(context, entries, &mask)) != 0)
        goto cleanup;

    if ((mask & tkt_mask) == tkt_mask)
        goto cleanup;

    if (policy != NULL) {
        st = krb5_ldap_read_policy(context, policy, &tktpoldnparam, &omask);
        if (st && st != KRB5_KDB_NOENTRY) {
            prepend_err_str(context, _("Error reading ticket policy. "), st,
                            st);
            goto cleanup;
        }

        st = 0; /* reset the return status */
    }

    if ((mask & KDB_MAX_LIFE_ATTR) == 0) {
        if ((omask & KDB_MAX_LIFE_ATTR) ==  KDB_MAX_LIFE_ATTR)
            entries->max_life = tktpoldnparam->maxtktlife;
        else if (ldap_context->lrparams->max_life)
            entries->max_life = ldap_context->lrparams->max_life;
    }

    if ((mask & KDB_MAX_RLIFE_ATTR) == 0) {
        if ((omask & KDB_MAX_RLIFE_ATTR) == KDB_MAX_RLIFE_ATTR)
            entries->max_renewable_life = tktpoldnparam->maxrenewlife;
        else if (ldap_context->lrparams->max_renewable_life)
            entries->max_renewable_life = ldap_context->lrparams->max_renewable_life;
    }

    if ((mask & KDB_TKT_FLAGS_ATTR) == 0) {
        if ((omask & KDB_TKT_FLAGS_ATTR) == KDB_TKT_FLAGS_ATTR)
            entries->attributes = tktpoldnparam->tktflags;
        else if (ldap_context->lrparams->tktflags)
            entries->attributes |= ldap_context->lrparams->tktflags;
    }
    krb5_ldap_free_policy(context, tktpoldnparam);

cleanup:
    return st;
}
Exemplo n.º 3
0
/* Ensure that we have the parameters we need to authenticate to the LDAP
 * server.  Read the password if necessary. */
static krb5_error_code
validate_context(krb5_context context, krb5_ldap_context *ctx)
{
    krb5_error_code ret;

    if (ctx->sasl_mech != NULL) {
        /* Read the password for use as the SASL secret if we can, but do not
         * require one as not all mechanisms need it. */
        if (ctx->bind_pwd == NULL && ctx->sasl_authcid != NULL &&
            ctx->service_password_file != NULL) {
            (void)krb5_ldap_readpassword(context, ctx->service_password_file,
                                         ctx->sasl_authcid, &ctx->bind_pwd);
        }
        return 0;
    }

    /* For a simple bind, a DN and password are required. */

    if (ctx->bind_dn == NULL) {
        k5_setmsg(context, EINVAL, _("LDAP bind dn value missing"));
        return EINVAL;
    }

    if (ctx->bind_pwd == NULL && ctx->service_password_file == NULL) {
        k5_setmsg(context, EINVAL, _("LDAP bind password value missing"));
        return EINVAL;
    }

    if (ctx->bind_pwd == NULL && ctx->service_password_file != NULL) {
        ret = krb5_ldap_readpassword(context, ctx->service_password_file,
                                     ctx->bind_dn, &ctx->bind_pwd);
        if (ret) {
            prepend_err_str(context, _("Error reading password from stash: "),
                            ret, ret);
            return ret;
        }
    }

    /* An empty password is not allowed. */
    if (*ctx->bind_pwd == '\0') {
        k5_setmsg(context, EINVAL, _("Service password length is zero"));
        return EINVAL;
    }

    return 0;
}
Exemplo n.º 4
0
/*
 * This function will create a krbcontainer and realm on the LDAP Server, with
 * the specified attributes.
 */
krb5_error_code
krb5_ldap_create(krb5_context context, char *conf_section, char **db_args)
{
    krb5_error_code status = 0;
    char  **t_ptr = db_args;
    krb5_ldap_realm_params *rparams = NULL;
    kdb5_dal_handle *dal_handle = NULL;
    krb5_ldap_context *ldap_context=NULL;
    krb5_boolean realm_obj_created = FALSE;
    krb5_boolean krbcontainer_obj_created = FALSE;
    krb5_ldap_krbcontainer_params kparams = {0};
    int srv_cnt = 0;
    int mask = 0;

    /* Clear the global error string */
    krb5_clear_error_message(context);

    ldap_context = malloc(sizeof(krb5_ldap_context));
    if (ldap_context == NULL) {
        status = ENOMEM;
        goto cleanup;
    }
    memset(ldap_context, 0, sizeof(*ldap_context));

    ldap_context->kcontext = context;

    /* populate ldap_context with ldap specific options */
    while (t_ptr && *t_ptr) {
        char *opt = NULL, *val = NULL;

        if ((status = krb5_ldap_get_db_opt(*t_ptr, &opt, &val)) != 0) {
            goto cleanup;
        }
        if (opt && !strcmp(opt, "binddn")) {
            if (ldap_context->bind_dn) {
                free (opt);
                free (val);
                status = EINVAL;
                krb5_set_error_message (context, status, "'binddn' missing");
                goto cleanup;
            }
            if (val == NULL) {
                status = EINVAL;
                krb5_set_error_message (context, status, "'binddn' value missing");
                free(opt);
                goto cleanup;
            }
            ldap_context->bind_dn = strdup(val);
            if (ldap_context->bind_dn == NULL) {
                free (opt);
                free (val);
                status = ENOMEM;
                goto cleanup;
            }
        } else if (opt && !strcmp(opt, "nconns")) {
            if (ldap_context->max_server_conns) {
                free (opt);
                free (val);
                status = EINVAL;
                krb5_set_error_message (context, status, "'nconns' missing");
                goto cleanup;
            }
            if (val == NULL) {
                status = EINVAL;
                krb5_set_error_message (context, status, "'nconns' value missing");
                free(opt);
                goto cleanup;
            }
            ldap_context->max_server_conns = atoi(val) ? atoi(val) : DEFAULT_CONNS_PER_SERVER;
        } else if (opt && !strcmp(opt, "bindpwd")) {
            if (ldap_context->bind_pwd) {
                free (opt);
                free (val);
                status = EINVAL;
                krb5_set_error_message (context, status, "'bindpwd' missing");
                goto cleanup;
            }
            if (val == NULL) {
                status = EINVAL;
                krb5_set_error_message (context, status, "'bindpwd' value missing");
                free(opt);
                goto cleanup;
            }
            ldap_context->bind_pwd = strdup(val);
            if (ldap_context->bind_pwd == NULL) {
                free (opt);
                free (val);
                status = ENOMEM;
                goto cleanup;
            }
        } else if (opt && !strcmp(opt, "host")) {
            if (val == NULL) {
                status = EINVAL;
                krb5_set_error_message (context, status, "'host' value missing");
                free(opt);
                goto cleanup;
            }
            if (ldap_context->server_info_list == NULL)
                ldap_context->server_info_list =
                    (krb5_ldap_server_info **) calloc(SERV_COUNT+1, sizeof(krb5_ldap_server_info *));

            if (ldap_context->server_info_list == NULL) {
                free (opt);
                free (val);
                status = ENOMEM;
                goto cleanup;
            }

            ldap_context->server_info_list[srv_cnt] =
                (krb5_ldap_server_info *) calloc(1, sizeof(krb5_ldap_server_info));
            if (ldap_context->server_info_list[srv_cnt] == NULL) {
                free (opt);
                free (val);
                status = ENOMEM;
                goto cleanup;
            }

            ldap_context->server_info_list[srv_cnt]->server_status = NOTSET;

            ldap_context->server_info_list[srv_cnt]->server_name = strdup(val);
            if (ldap_context->server_info_list[srv_cnt]->server_name == NULL) {
                free (opt);
                free (val);
                status = ENOMEM;
                goto cleanup;
            }

            srv_cnt++;
        } else {
            /* ignore hash argument. Might have been passed from create */
            status = EINVAL;
            if (opt && !strcmp(opt, "temporary")) {
                /*
                 * temporary is passed in when kdb5_util load without -update is done.
                 * This is unsupported by the LDAP plugin.
                 */
                krb5_set_error_message(context, status,
                                       _("creation of LDAP entries aborted, "
                                         "plugin requires -update argument"));
            } else {
                krb5_set_error_message(context, status,
                                       _("unknown option \'%s\'"),
                                       opt?opt:val);
            }
            free(opt);
            free(val);
            goto cleanup;
        }

        free(opt);
        free(val);
        t_ptr++;
    }

    dal_handle = context->dal_handle;
    dal_handle->db_context = (kdb5_dal_handle *) ldap_context;

    status = krb5_ldap_read_server_params(context, conf_section, KRB5_KDB_SRV_TYPE_ADMIN);
    if (status) {
        dal_handle->db_context = NULL;
        prepend_err_str (context, "Error reading LDAP server params: ", status, status);
        goto cleanup;
    }
    status = krb5_ldap_db_init(context, ldap_context);
    if (status) {
        goto cleanup;
    }

    /* read the kerberos container */
    if ((status = krb5_ldap_read_krbcontainer_params(context,
                                                     &(ldap_context->krbcontainer))) == KRB5_KDB_NOENTRY) {

        /* Read the kerberos container location from configuration file */
        if (ldap_context->conf_section) {
            if ((status = profile_get_string(context->profile,
                                             KDB_MODULE_SECTION, ldap_context->conf_section,
                                             KRB5_CONF_LDAP_KERBEROS_CONTAINER_DN, NULL,
                                             &kparams.DN)) != 0) {
                goto cleanup;
            }
        }
        if (kparams.DN == NULL) {
            if ((status = profile_get_string(context->profile,
                                             KDB_MODULE_DEF_SECTION,
                                             KRB5_CONF_LDAP_KERBEROS_CONTAINER_DN, NULL,
                                             NULL, &kparams.DN)) != 0) {
                goto cleanup;
            }
        }

        /* create the kerberos container */
        status = krb5_ldap_create_krbcontainer(context,
                                               ((kparams.DN != NULL) ? &kparams : NULL));
        if (status)
            goto cleanup;

        krbcontainer_obj_created = TRUE;

        status = krb5_ldap_read_krbcontainer_params(context,
                                                    &(ldap_context->krbcontainer));
        if (status)
            goto cleanup;

    } else if (status) {
        goto cleanup;
    }

    rparams = (krb5_ldap_realm_params *) malloc(sizeof(krb5_ldap_realm_params));
    if (rparams == NULL) {
        status = ENOMEM;
        goto cleanup;
    }
    memset(rparams, 0, sizeof(*rparams));
    rparams->realm_name = strdup(context->default_realm);
    if (rparams->realm_name == NULL) {
        status = ENOMEM;
        goto cleanup;
    }

    if ((status = krb5_ldap_create_realm(context, rparams, mask)))
        goto cleanup;

    /* We just created the Realm container. Here starts our transaction tracking */
    realm_obj_created = TRUE;

    /* verify realm object */
    if ((status = krb5_ldap_read_realm_params(context,
                                              rparams->realm_name,
                                              &(ldap_context->lrparams),
                                              &mask)))
        goto cleanup;

cleanup:

    /* If the krbcontainer/realm creation is not complete, do the roll-back here */
    if ((krbcontainer_obj_created) && (!realm_obj_created)) {
        int rc;
        rc = krb5_ldap_delete_krbcontainer(context,
                                           ((kparams.DN != NULL) ? &kparams : NULL));
        krb5_set_error_message(context, rc,
                               _("could not complete roll-back, error "
                                 "deleting Kerberos Container"));
    }

    /* should call krb5_ldap_free_krbcontainer_params() but can't */
    if (kparams.DN != NULL)
        krb5_xfree(kparams.DN);

    if (rparams)
        krb5_ldap_free_realm_params(rparams);

    return(status);
}
Exemplo n.º 5
0
/*
 * This function will create a krbcontainer and realm on the LDAP Server, with
 * the specified attributes.
 */
krb5_error_code
krb5_ldap_create (krb5_context context, char *conf_section, char **db_args)
{
    krb5_error_code status = 0;
    char  **t_ptr = db_args;
    krb5_ldap_realm_params *rparams = NULL;
    kdb5_dal_handle *dal_handle = NULL;
    krb5_ldap_context *ldap_context=NULL;
    krb5_boolean realm_obj_created = FALSE;
    krb5_boolean krbcontainer_obj_created = FALSE;
    krb5_ldap_krbcontainer_params kparams = {0};
    int srv_cnt = 0;
    int mask = 0;
#ifdef HAVE_EDIRECTORY
    int i = 0, rightsmask = 0;
#endif

    /* Clear the global error string */
    krb5_clear_error_message(context);

    ldap_context = malloc(sizeof(krb5_ldap_context));
    if (ldap_context == NULL) {
	status = ENOMEM;
	goto cleanup;
    }
    memset(ldap_context, 0, sizeof(*ldap_context));

    ldap_context->kcontext = context;

    /* populate ldap_context with ldap specific options */
    while (t_ptr && *t_ptr) {
	char *opt = NULL, *val = NULL;

	if ((status = krb5_ldap_get_db_opt(*t_ptr, &opt, &val)) != 0) {
	    goto cleanup;
	}
	if (opt && !strcmp(opt, "binddn")) {
	    if (ldap_context->bind_dn) {
		free (opt);
		free (val);
		status = EINVAL;
		krb5_set_error_message (context, status, gettext("'binddn' missing"));
		goto cleanup;
	    }
	    if (val == NULL) {
		status = EINVAL;
		krb5_set_error_message (context, status, gettext("'binddn' value missing"));
		free(opt);
		goto cleanup;
	    }
	    ldap_context->bind_dn = strdup(val);
	    if (ldap_context->bind_dn == NULL) {
		free (opt);
		free (val);
		status = ENOMEM;
		goto cleanup;
	    }
	} else if (opt && !strcmp(opt, "nconns")) {
	    if (ldap_context->max_server_conns) {
		free (opt);
		free (val);
		status = EINVAL;
		krb5_set_error_message (context, status, gettext("'nconns' missing"));
		goto cleanup;
	    }
	    if (val == NULL) {
		status = EINVAL;
		krb5_set_error_message (context, status, gettext("'nconns' value missing"));
		free(opt);
		goto cleanup;
	    }
	    ldap_context->max_server_conns = atoi(val) ? atoi(val) : DEFAULT_CONNS_PER_SERVER;
	} else if (opt && !strcmp(opt, "bindpwd")) {
	    if (ldap_context->bind_pwd) {
		free (opt);
		free (val);
		status = EINVAL;
		krb5_set_error_message (context, status, gettext("'bindpwd' missing"));
		goto cleanup;
	    }
	    if (val == NULL) {
		status = EINVAL;
		krb5_set_error_message (context, status, gettext("'bindpwd' value missing"));
		free(opt);
		goto cleanup;
	    }
	    ldap_context->bind_pwd = strdup(val);
	    if (ldap_context->bind_pwd == NULL) {
		free (opt);
		free (val);
		status = ENOMEM;
		goto cleanup;
	    }
	} else if (opt && !strcmp(opt, "host")) {
	    if (val == NULL) {
		status = EINVAL;
		krb5_set_error_message (context, status, gettext("'host' value missing"));
		free(opt);
		goto cleanup;
	    }
	    if (ldap_context->server_info_list == NULL)
		ldap_context->server_info_list =
		    (krb5_ldap_server_info **) calloc(SERV_COUNT+1, sizeof(krb5_ldap_server_info *));

	    if (ldap_context->server_info_list == NULL) {
		free (opt);
		free (val);
		status = ENOMEM;
		goto cleanup;
	    }

	    ldap_context->server_info_list[srv_cnt] =
		(krb5_ldap_server_info *) calloc(1, sizeof(krb5_ldap_server_info));
	    if (ldap_context->server_info_list[srv_cnt] == NULL) {
		free (opt);
		free (val);
		status = ENOMEM;
		goto cleanup;
	    }

	    ldap_context->server_info_list[srv_cnt]->server_status = NOTSET;

	    ldap_context->server_info_list[srv_cnt]->server_name = strdup(val);
	    if (ldap_context->server_info_list[srv_cnt]->server_name == NULL) {
		free (opt);
		free (val);
		status = ENOMEM;
		goto cleanup;
	    }

	    srv_cnt++;
#ifdef HAVE_EDIRECTORY
	} else if (opt && !strcmp(opt, "cert")) {
	    if (val == NULL) {
		status = EINVAL;
		krb5_set_error_message (context, status, gettext("'cert' value missing"));
		free(opt);
		goto cleanup;
	    }

	    if (ldap_context->root_certificate_file == NULL) {
		ldap_context->root_certificate_file = strdup(val);
		if (ldap_context->root_certificate_file == NULL) {
		    free (opt);
		    free (val);
		    status = ENOMEM;
		    goto cleanup;
		}
	    } else {
		void *tmp=NULL;
		char *oldstr = NULL;
		unsigned int len=0;

		oldstr = strdup(ldap_context->root_certificate_file);
		if (oldstr == NULL) {
		    free (opt);
		    free (val);
		    status = ENOMEM;
		    goto cleanup;
		}

		tmp = ldap_context->root_certificate_file;
		len = strlen(ldap_context->root_certificate_file) + 2 + strlen(val);
		ldap_context->root_certificate_file = realloc(ldap_context->root_certificate_file,
							      len);
		if (ldap_context->root_certificate_file == NULL) {
		    free (tmp);
		    free (opt);
		    free (val);
		    status = ENOMEM;
		    goto cleanup;
		}
		memset(ldap_context->root_certificate_file, 0, len);
		sprintf(ldap_context->root_certificate_file,"%s %s", oldstr, val);
		free (oldstr);
	    }
#endif
	} else {
	/* ignore hash argument. Might have been passed from create */
	    status = EINVAL;
	    if (opt && !strcmp(opt, "temporary")) {
		/* 
		 * temporary is passed in when kdb5_util load without -update is done.
		 * This is unsupported by the LDAP plugin.
		 */
		krb5_set_error_message (context, status,
		    gettext("creation of LDAP entries aborted, plugin requires -update argument"));
	    } else {
		krb5_set_error_message (context, status, gettext("unknown option \'%s\'"),
					opt?opt:val);
	    }
	    free(opt);
	    free(val);
	    goto cleanup;
	}

	free(opt);
	free(val);
	t_ptr++;
    }

    dal_handle = (kdb5_dal_handle *) context->db_context;
    dal_handle->db_context = (kdb5_dal_handle *) ldap_context;

    status = krb5_ldap_read_server_params(context, conf_section, KRB5_KDB_SRV_TYPE_ADMIN);
    if (status) {
	dal_handle->db_context = NULL;
	prepend_err_str (context, gettext("Error reading LDAP server params: "), status, status);
	goto cleanup;
    }
    status = krb5_ldap_db_init(context, ldap_context);
    if (status) {
	goto cleanup;
    }

    /* read the kerberos container */
    if ((status = krb5_ldap_read_krbcontainer_params(context,
			    &(ldap_context->krbcontainer))) == KRB5_KDB_NOENTRY) {

	/* Read the kerberos container location from configuration file */
	if (ldap_context->conf_section) {
	    if ((status = profile_get_string(context->profile,
					   KDB_MODULE_SECTION, ldap_context->conf_section,
					   "ldap_kerberos_container_dn", NULL,
					   &kparams.DN)) != 0) {
		goto cleanup;
	    }
	}
	if (kparams.DN == NULL) {
	    if ((status = profile_get_string(context->profile,
					   KDB_MODULE_DEF_SECTION,
					   "ldap_kerberos_container_dn", NULL,
					   NULL, &kparams.DN)) != 0) {
		goto cleanup;
	    }
	}

	/* create the kerberos container */
	status = krb5_ldap_create_krbcontainer(context,
					       ((kparams.DN != NULL) ? &kparams : NULL));
	if (status)
	    goto cleanup;

	krbcontainer_obj_created = TRUE;

	status = krb5_ldap_read_krbcontainer_params(context,
						    &(ldap_context->krbcontainer));
	if (status) {
	    krb5_set_error_message(context, status, gettext("while reading kerberos container information"));
	    goto cleanup;
	}

    } else if (status) {
	krb5_set_error_message(context, status, gettext("while reading kerberos container information"));
	goto cleanup;
    }

    rparams = (krb5_ldap_realm_params *) malloc(sizeof(krb5_ldap_realm_params));
    if (rparams == NULL) {
	status = ENOMEM;
	goto cleanup;
    }
    memset(rparams, 0, sizeof(*rparams));
    rparams->realm_name = strdup(context->default_realm);
    if (rparams->realm_name == NULL) {
	status = ENOMEM;
	goto cleanup;
    }

    if ((status = krb5_ldap_create_realm(context, rparams, mask))) {
	krb5_set_error_message(context, status, gettext("while creating realm object entry"));
	goto cleanup;
    }

    /* We just created the Realm container. Here starts our transaction tracking */
    realm_obj_created = TRUE;

    /* verify realm object */
    if ((status = krb5_ldap_read_realm_params(context,
					      rparams->realm_name,
					      &(ldap_context->lrparams),
					      &mask))) {
	krb5_set_error_message(context, status, gettext("while reading realm object entry"));
	goto cleanup;
    }

#ifdef HAVE_EDIRECTORY
    if ((mask & LDAP_REALM_KDCSERVERS) || (mask & LDAP_REALM_ADMINSERVERS) ||
	(mask & LDAP_REALM_PASSWDSERVERS)) {

	rightsmask =0;
	rightsmask |= LDAP_REALM_RIGHTS;
	rightsmask |= LDAP_SUBTREE_RIGHTS;
	if ((rparams != NULL) && (rparams->kdcservers != NULL)) {
	    for (i=0; (rparams->kdcservers[i] != NULL); i++) {
		if ((status=krb5_ldap_add_service_rights(context,
				     LDAP_KDC_SERVICE, rparams->kdcservers[i],
				     rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
		    goto cleanup;
		}
	    }
	}

	rightsmask = 0;
	rightsmask |= LDAP_REALM_RIGHTS;
	rightsmask |= LDAP_SUBTREE_RIGHTS;
	if ((rparams != NULL) && (rparams->adminservers != NULL)) {
	    for (i=0; (rparams->adminservers[i] != NULL); i++) {
		if ((status=krb5_ldap_add_service_rights(context,
				     LDAP_ADMIN_SERVICE, rparams->adminservers[i],
				     rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
		    goto cleanup;
		}
	    }
	}

	rightsmask = 0;
	rightsmask |= LDAP_REALM_RIGHTS;
	rightsmask |= LDAP_SUBTREE_RIGHTS;
	if ((rparams != NULL) && (rparams->passwdservers != NULL)) {
	    for (i=0; (rparams->passwdservers[i] != NULL); i++) {
		if ((status=krb5_ldap_add_service_rights(context,
				     LDAP_PASSWD_SERVICE, rparams->passwdservers[i],
				     rparams->realm_name, rparams->subtree, rightsmask)) != 0) {
		    goto cleanup;
		}
	    }
	}
    }
#endif

cleanup:

    /* If the krbcontainer/realm creation is not complete, do the roll-back here */
    if ((krbcontainer_obj_created) && (!realm_obj_created)) {
	int rc;
	rc = krb5_ldap_delete_krbcontainer(context,
		    ((kparams.DN != NULL) ? &kparams : NULL));
	krb5_set_error_message(context, rc,
	    gettext("could not complete roll-back, error deleting Kerberos Container"));
    }

    /* should call krb5_ldap_free_krbcontainer_params() but can't */
    if (kparams.DN != NULL)
	krb5_xfree(kparams.DN);

    if (rparams)
	krb5_ldap_free_realm_params(rparams);

    return(status);
}
Exemplo n.º 6
0
krb5_error_code
krb5_ldap_put_principal(krb5_context context, krb5_db_entry *entry,
                        char **db_args)
{
    int                         l=0, kerberos_principal_object_type=0;
    krb5_error_code             st=0, tempst=0;
    LDAP                        *ld=NULL;
    LDAPMessage                 *result=NULL, *ent=NULL;
    char                        *user=NULL, *subtree=NULL, *principal_dn=NULL;
    char                        **values=NULL, *strval[10]= {NULL}, errbuf[1024];
    struct berval               **bersecretkey=NULL;
    LDAPMod                     **mods=NULL;
    krb5_boolean                create_standalone_prinicipal=FALSE;
    krb5_boolean                krb_identity_exists=FALSE, establish_links=FALSE;
    char                        *standalone_principal_dn=NULL;
    krb5_tl_data                *tl_data=NULL;
    krb5_key_data               **keys=NULL;
    kdb5_dal_handle             *dal_handle=NULL;
    krb5_ldap_context           *ldap_context=NULL;
    krb5_ldap_server_handle     *ldap_server_handle=NULL;
    osa_princ_ent_rec           princ_ent;
    xargs_t                     xargs = {0};
    char                        *polname = NULL;
    OPERATION optype;
    krb5_boolean                found_entry = FALSE;

    /* Clear the global error string */
    krb5_clear_error_message(context);

    SETUP_CONTEXT();
    if (ldap_context->lrparams == NULL || ldap_context->krbcontainer == NULL)
        return EINVAL;

    /* get ldap handle */
    GET_HANDLE();

    if (is_principal_in_realm(ldap_context, entry->princ) != 0) {
        st = EINVAL;
        krb5_set_error_message(context, st, _("Principal does not belong to "
                                              "the default realm"));
        goto cleanup;
    }

    /* get the principal information to act on */
    if (entry->princ) {
        if (((st=krb5_unparse_name(context, entry->princ, &user)) != 0) ||
                ((st=krb5_ldap_unparse_principal_name(user)) != 0))
            goto cleanup;
    }

    /* Identity the type of operation, it can be
     * add principal or modify principal.
     * hack if the entry->mask has KRB_PRINCIPAL flag set
     * then it is a add operation
     */
    if (entry->mask & KADM5_PRINCIPAL)
        optype = ADD_PRINCIPAL;
    else
        optype = MODIFY_PRINCIPAL;

    if (((st=krb5_get_princ_type(context, entry, &kerberos_principal_object_type)) != 0) ||
            ((st=krb5_get_userdn(context, entry, &principal_dn)) != 0))
        goto cleanup;

    if ((st=process_db_args(context, db_args, &xargs, optype)) != 0)
        goto cleanup;

    if (entry->mask & KADM5_LOAD) {
        int              tree = 0, ntrees = 0, princlen = 0, numlentries = 0;
        char             **subtreelist = NULL, *filter = NULL;

        /*  A load operation is special, will do a mix-in (add krbprinc
         *  attrs to a non-krb object entry) if an object exists with a
         *  matching krbprincipalname attribute so try to find existing
         *  object and set principal_dn.  This assumes that the
         *  krbprincipalname attribute is unique (only one object entry has
         *  a particular krbprincipalname attribute).
         */
        if (user == NULL) {
            /* must have principal name for search */
            st = EINVAL;
            krb5_set_error_message(context, st,
                                   _("operation can not continue, principal "
                                     "name not found"));
            goto cleanup;
        }
        princlen = strlen(FILTER) + strlen(user) + 2 + 1;      /* 2 for closing brackets */
        if ((filter = malloc(princlen)) == NULL) {
            st = ENOMEM;
            goto cleanup;
        }
        snprintf(filter, princlen, FILTER"%s))", user);

        /* get the current subtree list */
        if ((st = krb5_get_subtree_info(ldap_context, &subtreelist, &ntrees)) != 0)
            goto cleanup;

        found_entry = FALSE;
        /* search for entry with matching krbprincipalname attribute */
        for (tree = 0; found_entry == FALSE && tree < ntrees; ++tree) {
            result = NULL;
            if (principal_dn == NULL) {
                LDAP_SEARCH_1(subtreelist[tree], ldap_context->lrparams->search_scope, filter, principal_attributes, IGNORE_STATUS);
            } else {
                /* just look for entry with principal_dn */
                LDAP_SEARCH_1(principal_dn, LDAP_SCOPE_BASE, filter, principal_attributes, IGNORE_STATUS);
            }
            if (st == LDAP_SUCCESS) {
                numlentries = ldap_count_entries(ld, result);
                if (numlentries > 1) {
                    ldap_msgfree(result);
                    free(filter);
                    st = EINVAL;
                    krb5_set_error_message(context, st,
                                           _("operation can not continue, "
                                             "more than one entry with "
                                             "principal name \"%s\" found"),
                                           user);
                    goto cleanup;
                } else if (numlentries == 1) {
                    found_entry = TRUE;
                    if (principal_dn == NULL) {
                        ent = ldap_first_entry(ld, result);
                        if (ent != NULL) {
                            /* setting principal_dn will cause that entry to be modified further down */
                            if ((principal_dn = ldap_get_dn(ld, ent)) == NULL) {
                                ldap_get_option (ld, LDAP_OPT_RESULT_CODE, &st);
                                st = set_ldap_error (context, st, 0);
                                ldap_msgfree(result);
                                free(filter);
                                goto cleanup;
                            }
                        }
                    }
                }
                if (result)
                    ldap_msgfree(result);
            } else if (st != LDAP_NO_SUCH_OBJECT) {
                /* could not perform search, return with failure */
                st = set_ldap_error (context, st, 0);
                free(filter);
                goto cleanup;
            }
            /*
             * If it isn't found then assume a standalone princ entry is to
             * be created.
             */
        } /* end for (tree = 0; principal_dn == ... */

        free(filter);

        if (found_entry == FALSE && principal_dn != NULL) {
            /*
             * if principal_dn is null then there is code further down to
             * deal with setting standalone_principal_dn.  Also note that
             * this will set create_standalone_prinicipal true for
             * non-mix-in entries which is okay if loading from a dump.
             */
            create_standalone_prinicipal = TRUE;
            standalone_principal_dn = strdup(principal_dn);
            CHECK_NULL(standalone_principal_dn);
        }
    } /* end if (entry->mask & KADM5_LOAD */

    /* time to generate the DN information with the help of
     * containerdn, principalcontainerreference or
     * realmcontainerdn information
     */
    if (principal_dn == NULL && xargs.dn == NULL) { /* creation of standalone principal */
        /* get the subtree information */
        if (entry->princ->length == 2 && entry->princ->data[0].length == strlen("krbtgt") &&
                strncmp(entry->princ->data[0].data, "krbtgt", entry->princ->data[0].length) == 0) {
            /* if the principal is a inter-realm principal, always created in the realm container */
            subtree = strdup(ldap_context->lrparams->realmdn);
        } else if (xargs.containerdn) {
            if ((st=checkattributevalue(ld, xargs.containerdn, NULL, NULL, NULL)) != 0) {
                if (st == KRB5_KDB_NOENTRY || st == KRB5_KDB_CONSTRAINT_VIOLATION) {
                    int ost = st;
                    st = EINVAL;
                    snprintf(errbuf, sizeof(errbuf), _("'%s' not found: "),
                             xargs.containerdn);
                    prepend_err_str(context, errbuf, st, ost);
                }
                goto cleanup;
            }
            subtree = strdup(xargs.containerdn);
        } else if (ldap_context->lrparams->containerref && strlen(ldap_context->lrparams->containerref) != 0) {
            /*
             * Here the subtree should be changed with
             * principalcontainerreference attribute value
             */
            subtree = strdup(ldap_context->lrparams->containerref);
        } else {
            subtree = strdup(ldap_context->lrparams->realmdn);
        }
        CHECK_NULL(subtree);

        if (asprintf(&standalone_principal_dn, "krbprincipalname=%s,%s",
                     user, subtree) < 0)
            standalone_principal_dn = NULL;
        CHECK_NULL(standalone_principal_dn);
        /*
         * free subtree when you are done using the subtree
         * set the boolean create_standalone_prinicipal to TRUE
         */
        create_standalone_prinicipal = TRUE;
        free(subtree);
        subtree = NULL;
    }

    /*
     * If the DN information is presented by the user, time to
     * validate the input to ensure that the DN falls under
     * any of the subtrees
     */
    if (xargs.dn_from_kbd == TRUE) {
        /* make sure the DN falls in the subtree */
        int              tre=0, dnlen=0, subtreelen=0, ntrees=0;
        char             **subtreelist=NULL;
        char             *dn=NULL;
        krb5_boolean     outofsubtree=TRUE;

        if (xargs.dn != NULL) {
            dn = xargs.dn;
        } else if (xargs.linkdn != NULL) {
            dn = xargs.linkdn;
        } else if (standalone_principal_dn != NULL) {
            /*
             * Even though the standalone_principal_dn is constructed
             * within this function, there is the containerdn input
             * from the user that can become part of the it.
             */
            dn = standalone_principal_dn;
        }

        /* get the current subtree list */
        if ((st = krb5_get_subtree_info(ldap_context, &subtreelist, &ntrees)) != 0)
            goto cleanup;

        for (tre=0; tre<ntrees; ++tre) {
            if (subtreelist[tre] == NULL || strlen(subtreelist[tre]) == 0) {
                outofsubtree = FALSE;
                break;
            } else {
                dnlen = strlen (dn);
                subtreelen = strlen(subtreelist[tre]);
                if ((dnlen >= subtreelen) && (strcasecmp((dn + dnlen - subtreelen), subtreelist[tre]) == 0)) {
                    outofsubtree = FALSE;
                    break;
                }
            }
        }

        for (tre=0; tre < ntrees; ++tre) {
            free(subtreelist[tre]);
        }

        if (outofsubtree == TRUE) {
            st = EINVAL;
            krb5_set_error_message(context, st,
                                   _("DN is out of the realm subtree"));
            goto cleanup;
        }

        /*
         * dn value will be set either by dn, linkdn or the standalone_principal_dn
         * In the first 2 cases, the dn should be existing and in the last case we
         * are supposed to create the ldap object. so the below should not be
         * executed for the last case.
         */

        if (standalone_principal_dn == NULL) {
            /*
             * If the ldap object is missing, this results in an error.
             */

            /*
             * Search for krbprincipalname attribute here.
             * This is to find if a kerberos identity is already present
             * on the ldap object, in which case adding a kerberos identity
             * on the ldap object should result in an error.
             */
            char  *attributes[]= {"krbticketpolicyreference", "krbprincipalname", NULL};

            LDAP_SEARCH_1(dn, LDAP_SCOPE_BASE, 0, attributes, IGNORE_STATUS);
            if (st == LDAP_SUCCESS) {
                ent = ldap_first_entry(ld, result);
                if (ent != NULL) {
                    if ((values=ldap_get_values(ld, ent, "krbticketpolicyreference")) != NULL) {
                        ldap_value_free(values);
                    }

                    if ((values=ldap_get_values(ld, ent, "krbprincipalname")) != NULL) {
                        krb_identity_exists = TRUE;
                        ldap_value_free(values);
                    }
                }
                ldap_msgfree(result);
            } else {
                st = set_ldap_error(context, st, OP_SEARCH);
                goto cleanup;
            }
        }
    }

    /*
     * If xargs.dn is set then the request is to add a
     * kerberos principal on a ldap object, but if
     * there is one already on the ldap object this
     * should result in an error.
     */

    if (xargs.dn != NULL && krb_identity_exists == TRUE) {
        st = EINVAL;
        snprintf(errbuf, sizeof(errbuf),
                 _("ldap object is already kerberized"));
        krb5_set_error_message(context, st, "%s", errbuf);
        goto cleanup;
    }

    if (xargs.linkdn != NULL) {
        /*
         * link information can be changed using modprinc.
         * However, link information can be changed only on the
         * standalone kerberos principal objects. A standalone
         * kerberos principal object is of type krbprincipal
         * structural objectclass.
         *
         * NOTE: kerberos principals on an ldap object can't be
         * linked to other ldap objects.
         */
        if (optype == MODIFY_PRINCIPAL &&
                kerberos_principal_object_type != KDB_STANDALONE_PRINCIPAL_OBJECT) {
            st = EINVAL;
            snprintf(errbuf, sizeof(errbuf),
                     _("link information can not be set/updated as the "
                       "kerberos principal belongs to an ldap object"));
            krb5_set_error_message(context, st, "%s", errbuf);
            goto cleanup;
        }
        /*
         * Check the link information. If there is already a link
         * existing then this operation is not allowed.
         */
        {
            char **linkdns=NULL;
            int  j=0;

            if ((st=krb5_get_linkdn(context, entry, &linkdns)) != 0) {
                snprintf(errbuf, sizeof(errbuf),
                         _("Failed getting object references"));
                krb5_set_error_message(context, st, "%s", errbuf);
                goto cleanup;
            }
            if (linkdns != NULL) {
                st = EINVAL;
                snprintf(errbuf, sizeof(errbuf),
                         _("kerberos principal is already linked to a ldap "
                           "object"));
                krb5_set_error_message(context, st, "%s", errbuf);
                for (j=0; linkdns[j] != NULL; ++j)
                    free (linkdns[j]);
                free (linkdns);
                goto cleanup;
            }
        }

        establish_links = TRUE;
    }

    if (entry->mask & KADM5_LAST_SUCCESS) {
        memset(strval, 0, sizeof(strval));
        if ((strval[0]=getstringtime(entry->last_success)) == NULL)
            goto cleanup;
        if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastSuccessfulAuth", LDAP_MOD_REPLACE, strval)) != 0) {
            free (strval[0]);
            goto cleanup;
        }
        free (strval[0]);
    }

    if (entry->mask & KADM5_LAST_FAILED) {
        memset(strval, 0, sizeof(strval));
        if ((strval[0]=getstringtime(entry->last_failed)) == NULL)
            goto cleanup;
        if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastFailedAuth", LDAP_MOD_REPLACE, strval)) != 0) {
            free (strval[0]);
            goto cleanup;
        }
        free(strval[0]);
    }

    if (entry->mask & KADM5_FAIL_AUTH_COUNT) {
        krb5_kvno fail_auth_count;

        fail_auth_count = entry->fail_auth_count;
        if (entry->mask & KADM5_FAIL_AUTH_COUNT_INCREMENT)
            fail_auth_count++;

        st = krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount",
                                       LDAP_MOD_REPLACE,
                                       fail_auth_count);
        if (st != 0)
            goto cleanup;
    } else if (entry->mask & KADM5_FAIL_AUTH_COUNT_INCREMENT) {
        int attr_mask = 0;
        krb5_boolean has_fail_count;

        /* Check if the krbLoginFailedCount attribute exists.  (Through
         * krb5 1.8.1, it wasn't set in new entries.) */
        st = krb5_get_attributes_mask(context, entry, &attr_mask);
        if (st != 0)
            goto cleanup;
        has_fail_count = ((attr_mask & KDB_FAIL_AUTH_COUNT_ATTR) != 0);

        /*
         * If the client library and server supports RFC 4525,
         * then use it to increment by one the value of the
         * krbLoginFailedCount attribute. Otherwise, assert the
         * (provided) old value by deleting it before adding.
         */
#ifdef LDAP_MOD_INCREMENT
        if (ldap_server_handle->server_info->modify_increment &&
                has_fail_count) {
            st = krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount",
                                           LDAP_MOD_INCREMENT, 1);
            if (st != 0)
                goto cleanup;
        } else {
#endif /* LDAP_MOD_INCREMENT */
            if (has_fail_count) {
                st = krb5_add_int_mem_ldap_mod(&mods,
                                               "krbLoginFailedCount",
                                               LDAP_MOD_DELETE,
                                               entry->fail_auth_count);
                if (st != 0)
                    goto cleanup;
            }
            st = krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount",
                                           LDAP_MOD_ADD,
                                           entry->fail_auth_count + 1);
            if (st != 0)
                goto cleanup;
#ifdef LDAP_MOD_INCREMENT
        }
#endif
    } else if (optype == ADD_PRINCIPAL) {
        /* Initialize krbLoginFailedCount in new entries to help avoid a
         * race during the first failed login. */
        st = krb5_add_int_mem_ldap_mod(&mods, "krbLoginFailedCount",
                                       LDAP_MOD_ADD, 0);
    }

    if (entry->mask & KADM5_MAX_LIFE) {
        if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxticketlife", LDAP_MOD_REPLACE, entry->max_life)) != 0)
            goto cleanup;
    }

    if (entry->mask & KADM5_MAX_RLIFE) {
        if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbmaxrenewableage", LDAP_MOD_REPLACE,
                                          entry->max_renewable_life)) != 0)
            goto cleanup;
    }

    if (entry->mask & KADM5_ATTRIBUTES) {
        if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbticketflags", LDAP_MOD_REPLACE,
                                          entry->attributes)) != 0)
            goto cleanup;
    }

    if (entry->mask & KADM5_PRINCIPAL) {
        memset(strval, 0, sizeof(strval));
        strval[0] = user;
        if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalname", LDAP_MOD_REPLACE, strval)) != 0)
            goto cleanup;
    }

    if (entry->mask & KADM5_PRINC_EXPIRE_TIME) {
        memset(strval, 0, sizeof(strval));
        if ((strval[0]=getstringtime(entry->expiration)) == NULL)
            goto cleanup;
        if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalexpiration", LDAP_MOD_REPLACE, strval)) != 0) {
            free (strval[0]);
            goto cleanup;
        }
        free (strval[0]);
    }

    if (entry->mask & KADM5_PW_EXPIRATION) {
        memset(strval, 0, sizeof(strval));
        if ((strval[0]=getstringtime(entry->pw_expiration)) == NULL)
            goto cleanup;
        if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpasswordexpiration",
                                          LDAP_MOD_REPLACE,
                                          strval)) != 0) {
            free (strval[0]);
            goto cleanup;
        }
        free (strval[0]);
    }

    if (entry->mask & KADM5_POLICY) {
        memset(&princ_ent, 0, sizeof(princ_ent));
        for (tl_data=entry->tl_data; tl_data; tl_data=tl_data->tl_data_next) {
            if (tl_data->tl_data_type == KRB5_TL_KADM_DATA) {
                /* FIX ME: I guess the princ_ent should be freed after this call */
                if ((st = krb5_lookup_tl_kadm_data(tl_data, &princ_ent)) != 0) {
                    goto cleanup;
                }
            }
        }

        if (princ_ent.aux_attributes & KADM5_POLICY) {
            memset(strval, 0, sizeof(strval));
            if ((st = krb5_ldap_name_to_policydn (context, princ_ent.policy, &polname)) != 0)
                goto cleanup;
            strval[0] = polname;
            if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_REPLACE, strval)) != 0)
                goto cleanup;
        } else {
            st = EINVAL;
            krb5_set_error_message(context, st, "Password policy value null");
            goto cleanup;
        }
    } else if (entry->mask & KADM5_LOAD && found_entry == TRUE) {
        /*
         * a load is special in that existing entries must have attrs that
         * removed.
         */

        if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_REPLACE, NULL)) != 0)
            goto cleanup;
    }

    if (entry->mask & KADM5_POLICY_CLR) {
        if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbpwdpolicyreference", LDAP_MOD_DELETE, NULL)) != 0)
            goto cleanup;
    }

    if (entry->mask & KADM5_KEY_DATA || entry->mask & KADM5_KVNO) {
        krb5_kvno mkvno;

        if ((st=krb5_dbe_lookup_mkvno(context, entry, &mkvno)) != 0)
            goto cleanup;
        bersecretkey = krb5_encode_krbsecretkey (entry->key_data,
                       entry->n_key_data, mkvno);

        if ((st=krb5_add_ber_mem_ldap_mod(&mods, "krbprincipalkey",
                                          LDAP_MOD_REPLACE | LDAP_MOD_BVALUES, bersecretkey)) != 0)
            goto cleanup;

        if (!(entry->mask & KADM5_PRINCIPAL)) {
            memset(strval, 0, sizeof(strval));
            if ((strval[0]=getstringtime(entry->pw_expiration)) == NULL)
                goto cleanup;
            if ((st=krb5_add_str_mem_ldap_mod(&mods,
                                              "krbpasswordexpiration",
                                              LDAP_MOD_REPLACE, strval)) != 0) {
                free (strval[0]);
                goto cleanup;
            }
            free (strval[0]);
        }

        /* Update last password change whenever a new key is set */
        {
            krb5_timestamp last_pw_changed;
            if ((st=krb5_dbe_lookup_last_pwd_change(context, entry,
                                                    &last_pw_changed)) != 0)
                goto cleanup;

            memset(strval, 0, sizeof(strval));
            if ((strval[0] = getstringtime(last_pw_changed)) == NULL)
                goto cleanup;

            if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastPwdChange",
                                              LDAP_MOD_REPLACE, strval)) != 0) {
                free (strval[0]);
                goto cleanup;
            }
            free (strval[0]);
        }

    } /* Modify Key data ends here */

    /* Set tl_data */
    if (entry->tl_data != NULL) {
        int count = 0;
        struct berval **ber_tl_data = NULL;
        krb5_tl_data *ptr;
        krb5_timestamp unlock_time;
        for (ptr = entry->tl_data; ptr != NULL; ptr = ptr->tl_data_next) {
            if (ptr->tl_data_type == KRB5_TL_LAST_PWD_CHANGE
#ifdef SECURID
                    || ptr->tl_data_type == KRB5_TL_DB_ARGS
#endif
                    || ptr->tl_data_type == KRB5_TL_KADM_DATA
                    || ptr->tl_data_type == KDB_TL_USER_INFO
                    || ptr->tl_data_type == KRB5_TL_CONSTRAINED_DELEGATION_ACL
                    || ptr->tl_data_type == KRB5_TL_LAST_ADMIN_UNLOCK)
                continue;
            count++;
        }
        if (count != 0) {
            int j;
            ber_tl_data = (struct berval **) calloc (count + 1,
                          sizeof (struct berval*));
            if (ber_tl_data == NULL) {
                st = ENOMEM;
                goto cleanup;
            }
            for (j = 0, ptr = entry->tl_data; ptr != NULL; ptr = ptr->tl_data_next) {
                /* Ignore tl_data that are stored in separate directory
                 * attributes */
                if (ptr->tl_data_type == KRB5_TL_LAST_PWD_CHANGE
#ifdef SECURID
                        || ptr->tl_data_type == KRB5_TL_DB_ARGS
#endif
                        || ptr->tl_data_type == KRB5_TL_KADM_DATA
                        || ptr->tl_data_type == KDB_TL_USER_INFO
                        || ptr->tl_data_type == KRB5_TL_CONSTRAINED_DELEGATION_ACL
                        || ptr->tl_data_type == KRB5_TL_LAST_ADMIN_UNLOCK)
                    continue;
                if ((st = tl_data2berval (ptr, &ber_tl_data[j])) != 0)
                    break;
                j++;
            }
            if (st == 0) {
                ber_tl_data[count] = NULL;
                st=krb5_add_ber_mem_ldap_mod(&mods, "krbExtraData",
                                             LDAP_MOD_REPLACE |
                                             LDAP_MOD_BVALUES, ber_tl_data);
            }
            for (j = 0; ber_tl_data[j] != NULL; j++) {
                free(ber_tl_data[j]->bv_val);
                free(ber_tl_data[j]);
            }
            free(ber_tl_data);
            if (st != 0)
                goto cleanup;
        }
        if ((st=krb5_dbe_lookup_last_admin_unlock(context, entry,
                &unlock_time)) != 0)
            goto cleanup;
        if (unlock_time != 0) {
            /* Update last admin unlock */
            memset(strval, 0, sizeof(strval));
            if ((strval[0] = getstringtime(unlock_time)) == NULL)
                goto cleanup;

            if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbLastAdminUnlock",
                                              LDAP_MOD_REPLACE, strval)) != 0) {
                free (strval[0]);
                goto cleanup;
            }
            free (strval[0]);
        }
    }

    /* Directory specific attribute */
    if (xargs.tktpolicydn != NULL) {
        int tmask=0;

        if (strlen(xargs.tktpolicydn) != 0) {
            st = checkattributevalue(ld, xargs.tktpolicydn, "objectclass", policyclass, &tmask);
            CHECK_CLASS_VALIDITY(st, tmask, _("ticket policy object value: "));

            strval[0] = xargs.tktpolicydn;
            strval[1] = NULL;
            if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbticketpolicyreference", LDAP_MOD_REPLACE, strval)) != 0)
                goto cleanup;

        } else {
            /* if xargs.tktpolicydn is a empty string, then delete
             * already existing krbticketpolicyreference attr */
            if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbticketpolicyreference", LDAP_MOD_DELETE, NULL)) != 0)
                goto cleanup;
        }

    }

    if (establish_links == TRUE) {
        memset(strval, 0, sizeof(strval));
        strval[0] = xargs.linkdn;
        if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbObjectReferences", LDAP_MOD_REPLACE, strval)) != 0)
            goto cleanup;
    }

    /*
     * in case mods is NULL then return
     * not sure but can happen in a modprinc
     * so no need to return an error
     * addprinc will at least have the principal name
     * and the keys passed in
     */
    if (mods == NULL)
        goto cleanup;

    if (create_standalone_prinicipal == TRUE) {
        memset(strval, 0, sizeof(strval));
        strval[0] = "krbprincipal";
        strval[1] = "krbprincipalaux";
        strval[2] = "krbTicketPolicyAux";

        if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
            goto cleanup;

        st = ldap_add_ext_s(ld, standalone_principal_dn, mods, NULL, NULL);
        if (st == LDAP_ALREADY_EXISTS && entry->mask & KADM5_LOAD) {
            /* a load operation must replace an existing entry */
            st = ldap_delete_ext_s(ld, standalone_principal_dn, NULL, NULL);
            if (st != LDAP_SUCCESS) {
                snprintf(errbuf, sizeof(errbuf),
                         _("Principal delete failed (trying to replace "
                           "entry): %s"), ldap_err2string(st));
                st = translate_ldap_error (st, OP_ADD);
                krb5_set_error_message(context, st, "%s", errbuf);
                goto cleanup;
            } else {
                st = ldap_add_ext_s(ld, standalone_principal_dn, mods, NULL, NULL);
            }
        }
        if (st != LDAP_SUCCESS) {
            snprintf(errbuf, sizeof(errbuf), _("Principal add failed: %s"),
                     ldap_err2string(st));
            st = translate_ldap_error (st, OP_ADD);
            krb5_set_error_message(context, st, "%s", errbuf);
            goto cleanup;
        }
    } else {
        /*
         * Here existing ldap object is modified and can be related
         * to any attribute, so always ensure that the ldap
         * object is extended with all the kerberos related
         * objectclasses so that there are no constraint
         * violations.
         */
        {
            char *attrvalues[] = {"krbprincipalaux", "krbTicketPolicyAux", NULL};
            int p, q, r=0, amask=0;

            if ((st=checkattributevalue(ld, (xargs.dn) ? xargs.dn : principal_dn,
                                        "objectclass", attrvalues, &amask)) != 0)
                goto cleanup;

            memset(strval, 0, sizeof(strval));
            for (p=1, q=0; p<=2; p<<=1, ++q) {
                if ((p & amask) == 0)
                    strval[r++] = attrvalues[q];
            }
            if (r != 0) {
                if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
                    goto cleanup;
            }
        }
        if (xargs.dn != NULL)
            st=ldap_modify_ext_s(ld, xargs.dn, mods, NULL, NULL);
        else
            st = ldap_modify_ext_s(ld, principal_dn, mods, NULL, NULL);

        if (st != LDAP_SUCCESS) {
            snprintf(errbuf, sizeof(errbuf), _("User modification failed: %s"),
                     ldap_err2string(st));
            st = translate_ldap_error (st, OP_MOD);
            krb5_set_error_message(context, st, "%s", errbuf);
            goto cleanup;
        }

        if (entry->mask & KADM5_FAIL_AUTH_COUNT_INCREMENT)
            entry->fail_auth_count++;
    }

cleanup:
    if (user)
        free(user);

    free_xargs(xargs);

    if (standalone_principal_dn)
        free(standalone_principal_dn);

    if (principal_dn)
        free (principal_dn);

    if (polname != NULL)
        free(polname);

    if (subtree)
        free (subtree);

    if (bersecretkey) {
        for (l=0; bersecretkey[l]; ++l) {
            if (bersecretkey[l]->bv_val)
                free (bersecretkey[l]->bv_val);
            free (bersecretkey[l]);
        }
        free (bersecretkey);
    }

    if (keys)
        free (keys);

    ldap_mods_free(mods, 1);
    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
    return(st);
}
Exemplo n.º 7
0
krb5_error_code
krb5_ldap_delete_realm (krb5_context context, char *lrealm)
{
    LDAP                        *ld = NULL;
    krb5_error_code             st = 0, tempst=0;
    char                        **values=NULL, **subtrees=NULL, **policy=NULL;
    LDAPMessage                 **result_arr=NULL, *result = NULL, *ent = NULL;
    krb5_principal              principal;
    unsigned int                l=0, ntree=0;
    int                         i=0, j=0, mask=0;
    kdb5_dal_handle             *dal_handle = NULL;
    krb5_ldap_context           *ldap_context = NULL;
    krb5_ldap_server_handle     *ldap_server_handle = NULL;
    krb5_ldap_realm_params      *rparam=NULL;

    SETUP_CONTEXT ();

    if (lrealm == NULL) {
        st = EINVAL;
        k5_setmsg(context, st, _("Realm information not available"));
        goto cleanup;
    }

    if ((st=krb5_ldap_read_realm_params(context, lrealm, &rparam, &mask)) != 0)
        goto cleanup;

    /* get ldap handle */
    GET_HANDLE ();

    /* delete all the principals belonging to the realm in the tree */
    {
        char *attr[] = {"krbprincipalname", NULL}, *realm=NULL, filter[256];
        krb5_ldap_context lcontext;

        realm = ldap_filter_correct (lrealm);
        assert (sizeof (filter) >= sizeof ("(krbprincipalname=)") +
                strlen (realm) + 2 /* "*@" */ + 1);

        snprintf (filter, sizeof(filter), "(krbprincipalname=*@%s)", realm);
        free (realm);

        /* LDAP_SEARCH(NULL, LDAP_SCOPE_SUBTREE, filter, attr); */
        memset(&lcontext, 0, sizeof(krb5_ldap_context));
        lcontext.lrparams = rparam;
        if ((st=krb5_get_subtree_info(&lcontext, &subtrees, &ntree)) != 0)
            goto cleanup;

        result_arr = (LDAPMessage **)  calloc((unsigned int)ntree+1,
                                              sizeof(LDAPMessage *));
        if (result_arr == NULL) {
            st = ENOMEM;
            goto cleanup;
        }

        for (l=0; l < ntree; ++l) {
            LDAP_SEARCH(subtrees[l], rparam->search_scope, filter, attr);
            result_arr[l] = result;
        }
    }

    /* NOTE: Here all the principals should be cached and the ldap handle should be freed,
     * as a DAL-LDAP interface is called right down here. Caching might be constrained by
     * availability of the memory. The caching is not done, however there would be limit
     * on the minimum number of handles for a server and it is 2. As the DAL-LDAP is not
     * thread-safe this should suffice.
     */
    for (j=0; (result=result_arr[j]) != NULL; ++j) {
        for (ent = ldap_first_entry (ld, result); ent != NULL;
             ent = ldap_next_entry (ld, ent)) {
            if ((values = ldap_get_values(ld, ent, "krbPrincipalName")) != NULL) {
                for (i = 0; values[i] != NULL; ++i) {
                    krb5_parse_name(context, values[i], &principal);
                    if (principal_in_realm_2(principal, lrealm) == 0) {
                        st=krb5_ldap_delete_principal(context, principal);
                        if (st && st != KRB5_KDB_NOENTRY)
                            goto cleanup;
                    }
                    krb5_free_principal(context, principal);
                }
                ldap_value_free(values);
            }
        }
    }

    /* Delete all password policies */
    krb5_ldap_iterate_password_policy (context, "*", delete_password_policy, context);

    /* Delete all ticket policies */
    {
        if ((st = krb5_ldap_list_policy (context, ldap_context->lrparams->realmdn, &policy)) != 0) {
            prepend_err_str(context, _("Error reading ticket policy: "), st,
                            st);
            goto cleanup;
        }

        for (i = 0; policy [i] != NULL; i++)
            krb5_ldap_delete_policy(context, policy[i]);
    }

    /* Delete the realm object */
    if ((st=ldap_delete_ext_s(ld, ldap_context->lrparams->realmdn, NULL, NULL)) != LDAP_SUCCESS) {
        int ost = st;
        st = translate_ldap_error (st, OP_DEL);
        k5_setmsg(context, st, _("Realm Delete FAILED: %s"),
                  ldap_err2string(ost));
    }

cleanup:
    if (subtrees) {
        for (l=0; l < ntree; ++l) {
            if (subtrees[l])
                free (subtrees[l]);
        }
        free (subtrees);
    }

    if (result_arr != NULL) {
        for (l = 0; l < ntree; l++)
            ldap_msgfree(result_arr[l]);
        free(result_arr);
    }

    if (policy != NULL) {
        for (i = 0; policy[i] != NULL; i++)
            free (policy[i]);
        free (policy);
    }

    krb5_ldap_free_realm_params(rparam);
    krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
    return st;
}