Exemplo n.º 1
0
/**
   \details Check if the user record which legacyExchangeDN points to
   belongs to the Exchange organization and is enabled

   \param dce_call pointer to the session context
   \param emsmdbp_ctx pointer to the EMSMDBP context
   \param legacyExchangeDN pointer to the userDN to lookup
   \param msg pointer on pointer to the LDB message matching the record

   \note Users can set msg to NULL if they do not intend to retrieve
   the message

   \return true on success, otherwise false
 */
_PUBLIC_ bool emsmdbp_verify_userdn(struct dcesrv_call_state *dce_call,
				    struct emsmdbp_context *emsmdbp_ctx,
				    const char *legacyExchangeDN,
				    struct ldb_message **msg)
{
	int			ret;
	int			msExchUserAccountControl;
	struct ldb_result	*res = NULL;
	const char * const	recipient_attrs[] = { "*", NULL };

	/* Sanity Checks */
	if (!legacyExchangeDN) return false;

	ret = ldb_search(emsmdbp_ctx->samdb_ctx, emsmdbp_ctx, &res,
			 ldb_get_default_basedn(emsmdbp_ctx->samdb_ctx),
			 LDB_SCOPE_SUBTREE, recipient_attrs, "(legacyExchangeDN=%s)",
			 legacyExchangeDN);

	/* If the search failed */
	if (ret != LDB_SUCCESS || !res->count) {
		return false;
	}

	/* Checks msExchUserAccountControl value */
	msExchUserAccountControl = ldb_msg_find_attr_as_int(res->msgs[0], "msExchUserAccountControl", 2);
	if (msExchUserAccountControl == 2) {
		return false;
	}

	if (msg) {
		*msg = res->msgs[0];
	}

	return true;
}
Exemplo n.º 2
0
/*
  unpack a ldb message into a GROUP_MAP structure
*/
static bool msg_to_group_map(struct ldb_message *msg, GROUP_MAP *map)
{
	const char *sidstr;

	map->gid          = ldb_msg_find_attr_as_int(msg, "gidNumber", -1);
	map->sid_name_use = ldb_msg_find_attr_as_int(msg, "sidNameUse", -1);
	fstrcpy(map->nt_name, ldb_msg_find_attr_as_string(msg, "ntName", NULL));
	fstrcpy(map->comment, ldb_msg_find_attr_as_string(msg, "comment", NULL));
	sidstr = ldb_msg_find_attr_as_string(msg, "sid", NULL);

	if (!string_to_sid(&map->sid, sidstr) ||
	    map->gid == (gid_t)-1 ||
	    map->sid_name_use == (enum lsa_SidType)-1) {
		DEBUG(0,("Unable to unpack group mapping\n"));
		return False;
	}

	return True;
}
Exemplo n.º 3
0
/* Was the krbtgt an RODC (and we are not) */
bool samba_krbtgt_was_untrusted_rodc(struct hdb_entry_ex *princ)
{

	struct samba_kdc_entry *p = talloc_get_type(princ->ctx, struct samba_kdc_entry);
	int rodc_krbtgt_number;

	/* Determine if this was printed by an RODC */
	rodc_krbtgt_number = ldb_msg_find_attr_as_int(p->msg, "msDS-SecondaryKrbTgtNumber", -1);
	if (rodc_krbtgt_number == -1) {
		return false;
	} else if (rodc_krbtgt_number != p->kdc_db_ctx->my_krbtgt_number) {
		return true;
	}

	return false;
}
Exemplo n.º 4
0
static void do_failed_login(struct LOCAL_request *lreq)
{
    int ret;
    int failedLoginAttempts;
    struct pam_data *pd;

    pd = lreq->preq->pd;
    pd->pam_status = PAM_AUTH_ERR;
/* TODO: maybe add more inteligent delay calculation */
    pd->response_delay = 3;

    lreq->mod_attrs = sysdb_new_attrs(lreq);
    NULL_CHECK_OR_JUMP(lreq->mod_attrs, ("sysdb_new_attrs failed.\n"),
                       lreq->error, ENOMEM, done);

    ret = sysdb_attrs_add_long(lreq->mod_attrs,
                               SYSDB_LAST_FAILED_LOGIN, (long)time(NULL));
    NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_long failed.\n"),
                      lreq->error, ret, done);

    failedLoginAttempts = ldb_msg_find_attr_as_int(lreq->res->msgs[0],
                                                   SYSDB_FAILED_LOGIN_ATTEMPTS,
                                                   0);
    failedLoginAttempts++;

    ret = sysdb_attrs_add_long(lreq->mod_attrs,
                               SYSDB_FAILED_LOGIN_ATTEMPTS,
                               (long)failedLoginAttempts);
    NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_attrs_add_long failed.\n"),
                      lreq->error, ret, done);

    ret = sysdb_set_user_attr(lreq->dbctx, lreq->domain,
                              lreq->preq->pd->user,
                              lreq->mod_attrs, SYSDB_MOD_REP);
    NEQ_CHECK_OR_JUMP(ret, EOK, ("sysdb_set_user_attr failed.\n"),
                      lreq->error, ret, done);

done:
    return;
}
Exemplo n.º 5
0
/**
   \details Check if the authenticated user belongs to the Exchange
   organization and is enabled

   \param dce_call pointer to the session context
   \param emsmdbp_ctx pointer to the EMSMDBP context

   \return true on success, otherwise false
 */
_PUBLIC_ bool emsmdbp_verify_user(struct dcesrv_call_state *dce_call,
				  struct emsmdbp_context *emsmdbp_ctx)
{
	int			ret;
	const char		*username = NULL;
	int			msExchUserAccountControl;
	struct ldb_result	*res = NULL;
	const char * const	recipient_attrs[] = { "msExchUserAccountControl", NULL };

	username = dcesrv_call_account_name(dce_call);

	ret = ldb_search(emsmdbp_ctx->samdb_ctx, emsmdbp_ctx, &res,
			 ldb_get_default_basedn(emsmdbp_ctx->samdb_ctx),
			 LDB_SCOPE_SUBTREE, recipient_attrs, "sAMAccountName=%s",
			 ldb_binary_encode_string(emsmdbp_ctx, username));

	/* If the search failed */
	if (ret != LDB_SUCCESS || !res->count) {
		return false;
	}

	/* If msExchUserAccountControl attribute is not found */
	if (!res->msgs[0]->num_elements) {
		return false;
	}

	/* If the attribute exists check its value */
	msExchUserAccountControl = ldb_msg_find_attr_as_int(res->msgs[0], "msExchUserAccountControl", 2);
	if (msExchUserAccountControl == 2) {
		return false;
	}

	/* Get a copy of the username for later use and setup missing conn_info components */
	emsmdbp_ctx->username = talloc_strdup(emsmdbp_ctx, username);
	openchangedb_get_MailboxReplica(emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, &emsmdbp_ctx->mstore_ctx->conn_info->repl_id, &emsmdbp_ctx->mstore_ctx->conn_info->replica_guid);

	return true;
}
Exemplo n.º 6
0
/**
   \details Get AD record for Mail-enabled account

   \param mem_ctx pointer to the session context
   \param emsabp_ctx pointer to the EMSABP context
   \param username User common name
   \param ldb_msg Pointer on pointer to ldb_message to return result to

   \return MAPI_E_SUCCESS on success, otherwise
   MAPI_E_NOT_ENOUGH_RESOURCES, MAPI_E_NOT_FOUND or
   MAPI_E_CORRUPT_STORE
 */
_PUBLIC_ enum MAPISTATUS emsabp_get_account_info(TALLOC_CTX *mem_ctx,
						 struct emsabp_context *emsabp_ctx,
						 const char *username,
						 struct ldb_message **ldb_msg)
{
	int			ret;
	int			msExchUserAccountControl;
	struct ldb_result	*res = NULL;
	const char * const	recipient_attrs[] = { "*", NULL };

	ret = ldb_search(emsabp_ctx->samdb_ctx, mem_ctx, &res,
			 ldb_get_default_basedn(emsabp_ctx->samdb_ctx),
			 LDB_SCOPE_SUBTREE, recipient_attrs, "CN=%s",
			 username);
	OPENCHANGE_RETVAL_IF((ret != LDB_SUCCESS || !res->count), MAPI_E_NOT_FOUND, NULL);

	/* Check if more than one record was found */
	OPENCHANGE_RETVAL_IF(res->count != 1, MAPI_E_CORRUPT_STORE, NULL);

	msExchUserAccountControl = ldb_msg_find_attr_as_int(res->msgs[0], "msExchUserAccountControl", -1);
	switch (msExchUserAccountControl) {
	case -1: /* msExchUserAccountControl attribute is not found */
		return MAPI_E_NOT_FOUND;
	case 0:
		*ldb_msg = res->msgs[0];
		return MAPI_E_SUCCESS;
	case 2: /* Account is disabled */
		*ldb_msg = res->msgs[0];
		return MAPI_E_ACCOUNT_DISABLED;
	default: /* Unknown value for msExchUserAccountControl attribute */
		return MAPI_E_CORRUPT_STORE;
	}
	
	/* We should never get here anyway */
	return MAPI_E_CORRUPT_STORE;
}
Exemplo n.º 7
0
/**
 * Fill in credentials for the machine trust account, from the secrets database.
 * 
 * @param cred Credentials structure to fill in
 * @retval NTSTATUS error detailing any failure
 */
NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred, 
				     const char *base,
				     const char *filter)
{
	TALLOC_CTX *mem_ctx;
	
	struct ldb_context *ldb;
	int ldb_ret;
	struct ldb_message **msgs;
	const char *attrs[] = {
		"secret",
		"priorSecret",
		"samAccountName",
		"flatname",
		"realm",
		"secureChannelType",
		"ntPwdHash",
		"msDS-KeyVersionNumber",
		"saltPrincipal",
		"privateKeytab",
		"krb5Keytab",
		NULL
	};
	
	const char *machine_account;
	const char *password;
	const char *old_password;
	const char *domain;
	const char *realm;
	enum netr_SchannelType sct;
	const char *salt_principal;
	const char *keytab;
	
	/* ok, we are going to get it now, don't recurse back here */
	cred->machine_account_pending = False;

	/* some other parts of the system will key off this */
	cred->machine_account = True;

	mem_ctx = talloc_named(cred, 0, "cli_credentials fetch machine password");

	/* Local secrets are stored in secrets.ldb */
	ldb = secrets_db_connect(mem_ctx);
	if (!ldb) {
		/* set anonymous as the fallback, if the machine account won't work */
		cli_credentials_set_anonymous(cred);
		DEBUG(1, ("Could not open secrets.ldb\n"));
		return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
	}

	/* search for the secret record */
	ldb_ret = gendb_search(ldb,
			       mem_ctx, ldb_dn_new(mem_ctx, ldb, base), 
			       &msgs, attrs,
			       "%s", filter);
	if (ldb_ret == 0) {
		DEBUG(1, ("Could not find entry to match filter: %s\n",
			  filter));
		/* set anonymous as the fallback, if the machine account won't work */
		cli_credentials_set_anonymous(cred);
		talloc_free(mem_ctx);
		return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
	} else if (ldb_ret != 1) {
		DEBUG(1, ("Found more than one (%d) entry to match filter: %s\n",
			  ldb_ret, filter));
		/* set anonymous as the fallback, if the machine account won't work */
		cli_credentials_set_anonymous(cred);
		talloc_free(mem_ctx);
		return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
	}
	
	password = ldb_msg_find_attr_as_string(msgs[0], "secret", NULL);
	old_password = ldb_msg_find_attr_as_string(msgs[0], "priorSecret", NULL);

	machine_account = ldb_msg_find_attr_as_string(msgs[0], "samAccountName", NULL);

	if (!machine_account) {
		DEBUG(1, ("Could not find 'samAccountName' in join record to domain: %s\n",
			  cli_credentials_get_domain(cred)));
		/* set anonymous as the fallback, if the machine account won't work */
		cli_credentials_set_anonymous(cred);
		talloc_free(mem_ctx);
		return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
	}

	salt_principal = ldb_msg_find_attr_as_string(msgs[0], "saltPrincipal", NULL);
	cli_credentials_set_salt_principal(cred, salt_principal);
	
	sct = ldb_msg_find_attr_as_int(msgs[0], "secureChannelType", 0);
	if (sct) { 
		cli_credentials_set_secure_channel_type(cred, sct);
	}
	
	if (!password) {
		const struct ldb_val *nt_password_hash = ldb_msg_find_ldb_val(msgs[0], "ntPwdHash");
		struct samr_Password hash;
		ZERO_STRUCT(hash);
		if (nt_password_hash) {
			memcpy(hash.hash, nt_password_hash->data, 
			       MIN(nt_password_hash->length, sizeof(hash.hash)));
		
			cli_credentials_set_nt_hash(cred, &hash, CRED_SPECIFIED);
		} else {
			cli_credentials_set_password(cred, NULL, CRED_SPECIFIED);
		}
	} else {
		cli_credentials_set_password(cred, password, CRED_SPECIFIED);
	}

	
	domain = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
	if (domain) {
		cli_credentials_set_domain(cred, domain, CRED_SPECIFIED);
	}

	realm = ldb_msg_find_attr_as_string(msgs[0], "realm", NULL);
	if (realm) {
		cli_credentials_set_realm(cred, realm, CRED_SPECIFIED);
	}

	cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED);

	cli_credentials_set_kvno(cred, ldb_msg_find_attr_as_int(msgs[0], "msDS-KeyVersionNumber", 0));

	/* If there was an external keytab specified by reference in
	 * the LDB, then use this.  Otherwise we will make one up
	 * (chewing CPU time) from the password */
	keytab = ldb_msg_find_attr_as_string(msgs[0], "krb5Keytab", NULL);
	if (keytab) {
		cli_credentials_set_keytab_name(cred, keytab, CRED_SPECIFIED);
	} else {
		keytab = ldb_msg_find_attr_as_string(msgs[0], "privateKeytab", NULL);
		if (keytab) {
			keytab = talloc_asprintf(mem_ctx, "FILE:%s", private_path(mem_ctx, keytab));
			if (keytab) {
				cli_credentials_set_keytab_name(cred, keytab, CRED_SPECIFIED);
			}
		}
	}
	talloc_free(mem_ctx);
	
	return NT_STATUS_OK;
}
Exemplo n.º 8
0
errno_t
sdap_idmap_init(TALLOC_CTX *mem_ctx,
                struct sdap_id_ctx *id_ctx,
                struct sdap_idmap_ctx **_idmap_ctx)
{
    errno_t ret;
    TALLOC_CTX *tmp_ctx;
    enum idmap_error_code err;
    size_t i;
    struct ldb_result *res;
    const char *dom_name;
    const char *sid_str;
    id_t slice_num;
    id_t idmap_lower;
    id_t idmap_upper;
    id_t rangesize;
    bool autorid_mode;
    struct sdap_idmap_ctx *idmap_ctx = NULL;

    tmp_ctx = talloc_new(NULL);
    if (!tmp_ctx) return ENOMEM;

    idmap_ctx = talloc_zero(tmp_ctx, struct sdap_idmap_ctx);
    if (!idmap_ctx) {
        ret = ENOMEM;
        goto done;
    }
    idmap_ctx->id_ctx = id_ctx;
    idmap_ctx->find_new_domain = sdap_idmap_find_new_domain;

    idmap_lower = dp_opt_get_int(idmap_ctx->id_ctx->opts->basic,
                                 SDAP_IDMAP_LOWER);
    idmap_upper = dp_opt_get_int(idmap_ctx->id_ctx->opts->basic,
                                 SDAP_IDMAP_UPPER);
    rangesize = dp_opt_get_int(idmap_ctx->id_ctx->opts->basic,
                               SDAP_IDMAP_RANGESIZE);
    autorid_mode = dp_opt_get_bool(idmap_ctx->id_ctx->opts->basic,
                                   SDAP_IDMAP_AUTORID_COMPAT);

    /* Validate that the values make sense */
    if (rangesize <= 0
            || idmap_upper <= idmap_lower
            || (idmap_upper-idmap_lower) < rangesize)
    {
        DEBUG(SSSDBG_FATAL_FAILURE,
              "Invalid settings for range selection: "
               "[%"SPRIid"][%"SPRIid"][%"SPRIid"]\n",
               idmap_lower, idmap_upper, rangesize);
        ret = EINVAL;
        goto done;
    }

    if (((idmap_upper - idmap_lower) % rangesize) != 0) {
        DEBUG(SSSDBG_CONF_SETTINGS,
              "Range size does not divide evenly. Uppermost range will "
               "not be used\n");
    }

    /* Initialize the map */
    err = sss_idmap_init(sss_idmap_talloc, idmap_ctx,
                         sss_idmap_talloc_free,
                         &idmap_ctx->map);
    if (err != IDMAP_SUCCESS) {
        DEBUG(SSSDBG_CRIT_FAILURE,
              "Could not initialize the ID map: [%s]\n",
               idmap_error_string(err));
        if (err == IDMAP_OUT_OF_MEMORY) {
            ret = ENOMEM;
        } else {
            ret = EINVAL;
        }
        goto done;
    }

    err = sss_idmap_ctx_set_autorid(idmap_ctx->map, autorid_mode);
    err |= sss_idmap_ctx_set_lower(idmap_ctx->map, idmap_lower);
    err |= sss_idmap_ctx_set_upper(idmap_ctx->map, idmap_upper);
    err |= sss_idmap_ctx_set_rangesize(idmap_ctx->map, rangesize);
    if (err != IDMAP_SUCCESS) {
        /* This should never happen */
        DEBUG(SSSDBG_CRIT_FAILURE, "sss_idmap_ctx corrupted\n");
        return EIO;
    }


    /* Setup range for externally managed IDs, i.e. IDs are read from the
     * ldap_user_uid_number and ldap_group_gid_number attributes. */
    if (!dp_opt_get_bool(idmap_ctx->id_ctx->opts->basic, SDAP_ID_MAPPING)) {
        ret = sdap_idmap_add_configured_external_range(idmap_ctx);
        if (ret != EOK) {
            DEBUG(SSSDBG_OP_FAILURE,
                  "sdap_idmap_add_configured_external_range failed.\n");
            goto done;
        }
    }

    /* Read in any existing mappings from the cache */
    ret = sysdb_idmap_get_mappings(tmp_ctx, id_ctx->be->domain, &res);
    if (ret != EOK && ret != ENOENT) {
        DEBUG(SSSDBG_FATAL_FAILURE,
              "Could not read ID mappings from the cache: [%s]\n",
               strerror(ret));
        goto done;
    }

    if (ret == EOK && res->count > 0) {
        DEBUG(SSSDBG_CONF_SETTINGS,
              "Initializing [%d] domains for ID-mapping\n", res->count);

        for (i = 0; i < res->count; i++) {
            dom_name = ldb_msg_find_attr_as_string(res->msgs[i],
                                                   SYSDB_NAME,
                                                   NULL);
            if (!dom_name) {
                /* This should never happen */
                ret = EINVAL;
                goto done;
            }

            sid_str = ldb_msg_find_attr_as_string(res->msgs[i],
                                                  SYSDB_IDMAP_SID_ATTR,
                                                  NULL);
            if (!sid_str) {
                /* This should never happen */
                ret = EINVAL;
                goto done;
            }

            slice_num = ldb_msg_find_attr_as_int(res->msgs[i],
                                                 SYSDB_IDMAP_SLICE_ATTR,
                                                 -1);
            if (slice_num == -1) {
                /* This should never happen */
                ret = EINVAL;
                goto done;
            }

            ret = sdap_idmap_add_domain(idmap_ctx, dom_name,
                                        sid_str, slice_num);
            if (ret != EOK) {
                DEBUG(SSSDBG_CRIT_FAILURE,
                      "Could not add domain [%s][%s][%"SPRIid"] "
                       "to ID map: [%s]\n",
                       dom_name, sid_str, slice_num, strerror(ret));
                goto done;
            }
        }
    } else {
        /* This is the first time we're setting up id-mapping
         * Store the default domain as slice 0
         */
        dom_name = dp_opt_get_string(idmap_ctx->id_ctx->opts->basic, SDAP_IDMAP_DEFAULT_DOMAIN);
        if (!dom_name) {
            /* If it's not explicitly specified, use the SSSD domain name */
            dom_name = idmap_ctx->id_ctx->be->domain->name;
            ret = dp_opt_set_string(idmap_ctx->id_ctx->opts->basic,
                                    SDAP_IDMAP_DEFAULT_DOMAIN,
                                    dom_name);
            if (ret != EOK) goto done;
        }

        sid_str = dp_opt_get_string(idmap_ctx->id_ctx->opts->basic, SDAP_IDMAP_DEFAULT_DOMAIN_SID);
        if (sid_str) {
            /* Set the default domain as slice 0 */
            ret = sdap_idmap_add_domain(idmap_ctx, dom_name,
                                        sid_str, 0);
            if (ret != EOK) {
                DEBUG(SSSDBG_CRIT_FAILURE,
                      "Could not add domain [%s][%s][%u] to ID map: [%s]\n",
                       dom_name, sid_str, 0, strerror(ret));
                goto done;
            }
        } else {
            if (dp_opt_get_bool(idmap_ctx->id_ctx->opts->basic, SDAP_IDMAP_AUTORID_COMPAT)) {
                /* In autorid compatibility mode, we MUST have a slice 0 */
                DEBUG(SSSDBG_CRIT_FAILURE,
                      "WARNING: Autorid compatibility mode selected, "
                       "but %s is not set. UID/GID values may differ "
                       "between clients.\n",
                       idmap_ctx->id_ctx->opts->basic[SDAP_IDMAP_DEFAULT_DOMAIN_SID].opt_name);
            }
            /* Otherwise, we'll just fall back to hash values as they are seen */
        }
    }

    *_idmap_ctx = talloc_steal(mem_ctx, idmap_ctx);
    ret = EOK;

done:
    talloc_free(tmp_ctx);
    return ret;
}
Exemplo n.º 9
0
/* 
  drsuapi_DsGetDomainControllerInfo 
*/
static WERROR dcesrv_drsuapi_DsGetDomainControllerInfo_1(struct drsuapi_bind_state *b_state, 
						TALLOC_CTX *mem_ctx,
						struct drsuapi_DsGetDomainControllerInfo *r)
{
	struct ldb_dn *sites_dn;
	struct ldb_result *res;

	const char *attrs_account_1[] = { "cn", "dnsHostName", NULL };
	const char *attrs_account_2[] = { "cn", "dnsHostName", "objectGUID", NULL };

	const char *attrs_none[] = { NULL };

	const char *attrs_site[] = { "objectGUID", NULL };

	const char *attrs_ntds[] = { "options", "objectGUID", NULL };

	const char *attrs_1[] = { "serverReference", "cn", "dnsHostName", NULL };
	const char *attrs_2[] = { "serverReference", "cn", "dnsHostName", "objectGUID", NULL };
	const char **attrs;

	struct drsuapi_DsGetDCInfoCtr1 *ctr1;
	struct drsuapi_DsGetDCInfoCtr2 *ctr2;

	int ret, i;

	*r->out.level_out = r->in.req->req1.level;
	r->out.ctr = talloc(mem_ctx, union drsuapi_DsGetDCInfoCtr);
	W_ERROR_HAVE_NO_MEMORY(r->out.ctr);

	sites_dn = samdb_sites_dn(b_state->sam_ctx, mem_ctx);
	if (!sites_dn) {
		return WERR_DS_OBJ_NOT_FOUND;
	}

	switch (*r->out.level_out) {
	case -1:
		/* this level is not like the others */
		return WERR_UNKNOWN_LEVEL;
	case 1:
		attrs = attrs_1;
		break;
	case 2:
		attrs = attrs_2;
		break;
	default:
		return WERR_UNKNOWN_LEVEL;
	}

	ret = ldb_search(b_state->sam_ctx, mem_ctx, &res, sites_dn, LDB_SCOPE_SUBTREE, attrs,
				 "objectClass=server");
	
	if (ret) {
		DEBUG(1, ("searching for servers in sites DN %s failed: %s\n", 
			  ldb_dn_get_linearized(sites_dn), ldb_errstring(b_state->sam_ctx)));
		return WERR_GENERAL_FAILURE;
	}

	switch (*r->out.level_out) {
	case 1:
		ctr1 = &r->out.ctr->ctr1;
		ctr1->count = res->count;
		ctr1->array = talloc_zero_array(mem_ctx, 
						struct drsuapi_DsGetDCInfo1, 
						res->count);
		for (i=0; i < res->count; i++) {
			struct ldb_dn *domain_dn;
			struct ldb_result *res_domain;
			struct ldb_result *res_account;
			struct ldb_dn *ntds_dn = ldb_dn_copy(mem_ctx, res->msgs[i]->dn);
			
			struct ldb_dn *ref_dn
				= ldb_msg_find_attr_as_dn(b_state->sam_ctx, 
							  mem_ctx, res->msgs[i], 
							  "serverReference");

			if (!ntds_dn || !ldb_dn_add_child_fmt(ntds_dn, "CN=NTDS Settings")) {
				return WERR_NOMEM;
			}

			ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_account, ref_dn,
						 LDB_SCOPE_BASE, attrs_account_1, "objectClass=computer");
			if (ret == LDB_SUCCESS && res_account->count == 1) {
				const char *errstr;
				ctr1->array[i].dns_name
					= ldb_msg_find_attr_as_string(res_account->msgs[0], "dNSHostName", NULL);
				ctr1->array[i].netbios_name
					= ldb_msg_find_attr_as_string(res_account->msgs[0], "cn", NULL);
				ctr1->array[i].computer_dn
					= ldb_dn_get_linearized(res_account->msgs[0]->dn);

				/* Determine if this is the PDC */
				ret = samdb_search_for_parent_domain(b_state->sam_ctx, 
								     mem_ctx, res_account->msgs[0]->dn,
								     &domain_dn, &errstr);
				
				if (ret == LDB_SUCCESS) {
					ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn,
								 LDB_SCOPE_BASE, attrs_none, "fSMORoleOwner=%s",
								 ldb_dn_get_linearized(ntds_dn));
					if (ret) {
						return WERR_GENERAL_FAILURE;
					}
					if (res_domain->count == 1) {
						ctr1->array[i].is_pdc = true;
					}
				}
			}
			if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
				DEBUG(5, ("warning: searching for computer DN %s failed: %s\n", 
					  ldb_dn_get_linearized(ref_dn), ldb_errstring(b_state->sam_ctx)));
			}

			/* Look at server DN and extract site component */
			ctr1->array[i].site_name = result_site_name(res->msgs[i]->dn);
			ctr1->array[i].server_dn = ldb_dn_get_linearized(res->msgs[i]->dn);


			ctr1->array[i].is_enabled = true;

		}
		break;
	case 2:
		ctr2 = &r->out.ctr->ctr2;
		ctr2->count = res->count;
		ctr2->array = talloc_zero_array(mem_ctx, 
						 struct drsuapi_DsGetDCInfo2, 
						 res->count);
		for (i=0; i < res->count; i++) {
			struct ldb_dn *domain_dn;
			struct ldb_result *res_domain;
			struct ldb_result *res_account;
			struct ldb_dn *ntds_dn = ldb_dn_copy(mem_ctx, res->msgs[i]->dn);
			struct ldb_result *res_ntds;
			struct ldb_dn *site_dn = ldb_dn_copy(mem_ctx, res->msgs[i]->dn);
			struct ldb_result *res_site;
			struct ldb_dn *ref_dn
				= ldb_msg_find_attr_as_dn(b_state->sam_ctx, 
							  mem_ctx, res->msgs[i], 
							  "serverReference");

			if (!ntds_dn || !ldb_dn_add_child_fmt(ntds_dn, "CN=NTDS Settings")) {
				return WERR_NOMEM;
			}

			/* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
			if (!site_dn || !ldb_dn_remove_child_components(site_dn, 2)) {
				return WERR_NOMEM;
			}

			ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_ntds, ntds_dn,
						 LDB_SCOPE_BASE, attrs_ntds, "objectClass=nTDSDSA");
			if (ret == LDB_SUCCESS && res_ntds->count == 1) {
				ctr2->array[i].is_gc
					= (ldb_msg_find_attr_as_int(res_ntds->msgs[0], "options", 0) == 1);
				ctr2->array[i].ntds_guid 
					= samdb_result_guid(res_ntds->msgs[0], "objectGUID");
				ctr2->array[i].ntds_dn = ldb_dn_get_linearized(res_ntds->msgs[0]->dn);
			}
			if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
				DEBUG(5, ("warning: searching for NTDS DN %s failed: %s\n", 
					  ldb_dn_get_linearized(ntds_dn), ldb_errstring(b_state->sam_ctx)));
			}

			ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_site, site_dn,
						 LDB_SCOPE_BASE, attrs_site, "objectClass=site");
			if (ret == LDB_SUCCESS && res_site->count == 1) {
				ctr2->array[i].site_guid 
					= samdb_result_guid(res_site->msgs[0], "objectGUID");
				ctr2->array[i].site_dn = ldb_dn_get_linearized(res_site->msgs[0]->dn);
			}
			if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
				DEBUG(5, ("warning: searching for site DN %s failed: %s\n", 
					  ldb_dn_get_linearized(site_dn), ldb_errstring(b_state->sam_ctx)));
			}

			ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_account, ref_dn,
						 LDB_SCOPE_BASE, attrs_account_2, "objectClass=computer");
			if (ret == LDB_SUCCESS && res_account->count == 1) {
				const char *errstr;
				ctr2->array[i].dns_name
					= ldb_msg_find_attr_as_string(res_account->msgs[0], "dNSHostName", NULL);
				ctr2->array[i].netbios_name
					= ldb_msg_find_attr_as_string(res_account->msgs[0], "cn", NULL);
				ctr2->array[i].computer_dn = ldb_dn_get_linearized(res_account->msgs[0]->dn);
				ctr2->array[i].computer_guid 
					= samdb_result_guid(res_account->msgs[0], "objectGUID");

				/* Determine if this is the PDC */
				ret = samdb_search_for_parent_domain(b_state->sam_ctx, 
								     mem_ctx, res_account->msgs[0]->dn,
								     &domain_dn, &errstr);
				
				if (ret == LDB_SUCCESS) {
					ret = ldb_search(b_state->sam_ctx, mem_ctx, &res_domain, domain_dn,
								 LDB_SCOPE_BASE, attrs_none, "fSMORoleOwner=%s",
								 ldb_dn_get_linearized(ntds_dn));
					if (ret == LDB_SUCCESS && res_domain->count == 1) {
						ctr2->array[i].is_pdc = true;
					}
					if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
						DEBUG(5, ("warning: searching for domain DN %s failed: %s\n", 
							  ldb_dn_get_linearized(domain_dn), ldb_errstring(b_state->sam_ctx)));
					}
				}
			}
			if ((ret != LDB_SUCCESS) && (ret != LDB_ERR_NO_SUCH_OBJECT)) {
				DEBUG(5, ("warning: searching for computer account DN %s failed: %s\n", 
					  ldb_dn_get_linearized(ref_dn), ldb_errstring(b_state->sam_ctx)));
			}

			/* Look at server DN and extract site component */
			ctr2->array[i].site_name = result_site_name(res->msgs[i]->dn);
			ctr2->array[i].server_dn = ldb_dn_get_linearized(res->msgs[i]->dn);
			ctr2->array[i].server_guid 
				= samdb_result_guid(res->msgs[i], "objectGUID");

			ctr2->array[i].is_enabled = true;

		}
		break;
	}
	return WERR_OK;
}
Exemplo n.º 10
0
bool torture_gpo_system_access_policies(struct torture_context *tctx)
{
	TALLOC_CTX *ctx = talloc_new(tctx);
	int ret, vers = 0, i;
	const char *sysvol_path = NULL, *gpo_dir = NULL;
	const char *gpo_file = NULL, *gpt_file = NULL;
	struct ldb_context *samdb = NULL;
	struct ldb_result *result;
	const char *attrs[] = {
		"minPwdAge",
		"maxPwdAge",
		"minPwdLength",
		"pwdProperties",
		NULL
	};
	FILE *fp = NULL;
	const char **gpo_update_cmd;
	char **gpo_unapply_cmd;
	int minpwdcases[] = { 0, 1, 998 };
	int maxpwdcases[] = { 0, 1, 999 };
	int pwdlencases[] = { 0, 1, 14 };
	int pwdpropcases[] = { 0, 1, 1 };
	struct ldb_message *old_message = NULL;
	const char **itr;
	int gpo_update_len = 0;

	sysvol_path = lpcfg_path(lpcfg_service(tctx->lp_ctx, "sysvol"),
				 lpcfg_default_service(tctx->lp_ctx), tctx);
	torture_assert(tctx, sysvol_path, "Failed to fetch the sysvol path");

	/* Ensure the sysvol path exists */
	gpo_dir = talloc_asprintf(ctx, "%s/%s", sysvol_path, GPODIR);
	mkdir_p(gpo_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
	gpo_file = talloc_asprintf(ctx, "%s/%s", gpo_dir, GPOFILE);

	/* Get the gpo update command */
	gpo_update_cmd = lpcfg_gpo_update_command(tctx->lp_ctx);
	torture_assert(tctx, gpo_update_cmd && gpo_update_cmd[0],
		       "Failed to fetch the gpo update command");

	/* Open and read the samba db and store the initial password settings */
	samdb = samdb_connect(ctx,
			      tctx->ev,
			      tctx->lp_ctx,
			      system_session(tctx->lp_ctx),
			      NULL,
			      0);
	torture_assert(tctx, samdb, "Failed to connect to the samdb");

	ret = ldb_search(samdb, ctx, &result, ldb_get_default_basedn(samdb),
			 LDB_SCOPE_BASE, attrs, NULL);
	torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
		       "Searching the samdb failed");

	old_message = result->msgs[0];

	for (i = 0; i < 3; i++) {
		/* Write out the sysvol */
		if ( (fp = fopen(gpo_file, "w")) ) {
			fputs(talloc_asprintf(ctx, GPTTMPL, minpwdcases[i],
					      maxpwdcases[i], pwdlencases[i],
					      pwdpropcases[i]), fp);
			fclose(fp);
		}

		/* Update the version in the GPT.INI */
		gpt_file = talloc_asprintf(ctx, "%s/%s", sysvol_path, GPTINI);
		if ( (fp = fopen(gpt_file, "r")) ) {
			char line[256];
			while (fgets(line, 256, fp)) {
				if (strncasecmp(line, "Version=", 8) == 0) {
					vers = atoi(line+8);
					break;
				}
			}
			fclose(fp);
		}
		if ( (fp = fopen(gpt_file, "w")) ) {
			char *data = talloc_asprintf(ctx,
						     "[General]\nVersion=%d\n",
						     ++vers);
			fputs(data, fp);
			fclose(fp);
		}

		/* Run the gpo update command */
		ret = exec_wait(discard_const_p(char *, gpo_update_cmd));
		torture_assert(tctx, ret == 0,
			       "Failed to execute the gpo update command");

		ret = ldb_search(samdb, ctx, &result,
				 ldb_get_default_basedn(samdb),
				 LDB_SCOPE_BASE, attrs, NULL);
		torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
			       "Searching the samdb failed");

		/* minPwdAge */
		torture_assert_int_equal(tctx, unix2nttime(
						ldb_msg_find_attr_as_string(
							result->msgs[0],
							attrs[0],
							"")), minpwdcases[i],
			       "The minPwdAge was not applied");

		/* maxPwdAge */
		torture_assert_int_equal(tctx, unix2nttime(
						ldb_msg_find_attr_as_string(
							result->msgs[0],
							attrs[1],
							"")), maxpwdcases[i],
			       "The maxPwdAge was not applied");

		/* minPwdLength */
		torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
							result->msgs[0],
							attrs[2],
							-1),
					       pwdlencases[i],
				"The minPwdLength was not applied");

		/* pwdProperties */
		torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
							result->msgs[0],
							attrs[3],
							-1),
					       pwdpropcases[i],
			       "The pwdProperties were not applied");
	}

	/* Unapply the settings and verify they are removed */
	for (itr = gpo_update_cmd; *itr != NULL; itr++) {
		gpo_update_len++;
	}
	gpo_unapply_cmd = talloc_array(ctx, char*, gpo_update_len+2);
	for (i = 0; i < gpo_update_len; i++) {
		gpo_unapply_cmd[i] = talloc_strdup(gpo_unapply_cmd,
						   gpo_update_cmd[i]);
	}
	gpo_unapply_cmd[i] = talloc_asprintf(gpo_unapply_cmd, "--unapply");
	gpo_unapply_cmd[i+1] = NULL;
	ret = exec_wait(gpo_unapply_cmd);
	torture_assert(tctx, ret == 0,
		       "Failed to execute the gpo unapply command");
	ret = ldb_search(samdb, ctx, &result, ldb_get_default_basedn(samdb),
			 LDB_SCOPE_BASE, attrs, NULL);
	torture_assert(tctx, ret == LDB_SUCCESS && result->count == 1,
		       "Searching the samdb failed");
	/* minPwdAge */
	torture_assert_int_equal(tctx, unix2nttime(ldb_msg_find_attr_as_string(
						result->msgs[0],
						attrs[0],
						"")),
		       unix2nttime(ldb_msg_find_attr_as_string(old_message,
							       attrs[0],
							       "")
				  ),
		       "The minPwdAge was not unapplied");
	/* maxPwdAge */
	torture_assert_int_equal(tctx, unix2nttime(ldb_msg_find_attr_as_string(
						result->msgs[0],
						attrs[1],
						"")),
		       unix2nttime(ldb_msg_find_attr_as_string(old_message,
							       attrs[1],
							       "")
				  ),
		       "The maxPwdAge was not unapplied");
	/* minPwdLength */
	torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
						result->msgs[0],
						attrs[2],
						-1),
				       ldb_msg_find_attr_as_int(
						old_message,
						attrs[2],
						-2),
			"The minPwdLength was not unapplied");
	/* pwdProperties */
	torture_assert_int_equal(tctx, ldb_msg_find_attr_as_int(
						result->msgs[0],
						attrs[3],
						-1),
					ldb_msg_find_attr_as_int(
						old_message,
						attrs[3],
						-2),
			"The pwdProperties were not unapplied");

	talloc_free(ctx);
	return true;
}
Exemplo n.º 11
0
/*
  read back a credentials back for a computer
*/
NTSTATUS schannel_fetch_session_key_ldb(struct ldb_context *ldb,
					TALLOC_CTX *mem_ctx,
					const char *computer_name,
					struct netlogon_creds_CredentialState **creds)
{
	struct ldb_result *res;
	int ret;
	const struct ldb_val *val;

	*creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState);
	if (!*creds) {
		return NT_STATUS_NO_MEMORY;
	}

	ret = ldb_search(ldb, mem_ctx, &res,
				 NULL, LDB_SCOPE_SUBTREE, NULL,
				"(computerName=%s)", computer_name);
	if (ret != LDB_SUCCESS) {
		DEBUG(3,("schannel: Failed to find a record for client %s: %s\n", computer_name, ldb_errstring(ldb)));
		return NT_STATUS_INVALID_HANDLE;
	}
	if (res->count != 1) {
		DEBUG(3,("schannel: Failed to find a record for client: %s (found %d records)\n", computer_name, res->count));
		talloc_free(res);
		return NT_STATUS_INVALID_HANDLE;
	}

	val = ldb_msg_find_ldb_val(res->msgs[0], "sessionKey");
	if (val == NULL || val->length != 16) {
		DEBUG(1,("schannel: record in schannel DB must contain a sessionKey of length 16, when searching for client: %s\n", computer_name));
		talloc_free(res);
		return NT_STATUS_INTERNAL_ERROR;
	}

	memcpy((*creds)->session_key, val->data, 16);

	val = ldb_msg_find_ldb_val(res->msgs[0], "seed");
	if (val == NULL || val->length != 8) {
		DEBUG(1,("schannel: record in schannel DB must contain a vaid seed of length 8, when searching for client: %s\n", computer_name));
		talloc_free(res);
		return NT_STATUS_INTERNAL_ERROR;
	}

	memcpy((*creds)->seed.data, val->data, 8);

	val = ldb_msg_find_ldb_val(res->msgs[0], "clientState");
	if (val == NULL || val->length != 8) {
		DEBUG(1,("schannel: record in schannel DB must contain a vaid clientState of length 8, when searching for client: %s\n", computer_name));
		talloc_free(res);
		return NT_STATUS_INTERNAL_ERROR;
	}
	memcpy((*creds)->client.data, val->data, 8);

	val = ldb_msg_find_ldb_val(res->msgs[0], "serverState");
	if (val == NULL || val->length != 8) {
		DEBUG(1,("schannel: record in schannel DB must contain a vaid serverState of length 8, when searching for client: %s\n", computer_name));
		talloc_free(res);
		return NT_STATUS_INTERNAL_ERROR;
	}
	memcpy((*creds)->server.data, val->data, 8);

	(*creds)->negotiate_flags = ldb_msg_find_attr_as_int(res->msgs[0], "negotiateFlags", 0);

	(*creds)->secure_channel_type = ldb_msg_find_attr_as_int(res->msgs[0], "secureChannelType", 0);

	(*creds)->account_name = talloc_strdup(*creds, ldb_msg_find_attr_as_string(res->msgs[0], "accountName", NULL));
	if ((*creds)->account_name == NULL) {
		talloc_free(res);
		return NT_STATUS_NO_MEMORY;
	}

	(*creds)->computer_name = talloc_strdup(*creds, ldb_msg_find_attr_as_string(res->msgs[0], "computerName", NULL));
	if ((*creds)->computer_name == NULL) {
		talloc_free(res);
		return NT_STATUS_NO_MEMORY;
	}

	val = ldb_msg_find_ldb_val(res->msgs[0], "objectSid");
	if (val) {
		(*creds)->sid = schannel_ldb_val_dom_sid(*creds, val);
		if ((*creds)->sid == NULL) {
			talloc_free(res);
			return NT_STATUS_INTERNAL_ERROR;
		}
	} else {
		(*creds)->sid = NULL;
	}

	talloc_free(res);
	return NT_STATUS_OK;
}
Exemplo n.º 12
0
WERROR dsdb_convert_object_ex(struct ldb_context *ldb,
			      const struct dsdb_schema *schema,
			      const struct dsdb_schema_prefixmap *pfm_remote,
			      const struct drsuapi_DsReplicaObjectListItemEx *in,
			      const DATA_BLOB *gensec_skey,
			      const uint32_t *ignore_attids,
			      uint32_t dsdb_repl_flags,
			      TALLOC_CTX *mem_ctx,
			      struct dsdb_extended_replicated_object *out)
{
	NTSTATUS nt_status;
	WERROR status = WERR_OK;
	uint32_t i;
	struct ldb_message *msg;
	struct replPropertyMetaDataBlob *md;
	int instanceType;
	struct ldb_message_element *instanceType_e = NULL;
	struct ldb_val guid_value;
	struct ldb_val parent_guid_value;
	NTTIME whenChanged = 0;
	time_t whenChanged_t;
	const char *whenChanged_s;
	struct drsuapi_DsReplicaAttribute *name_a = NULL;
	struct drsuapi_DsReplicaMetaData *name_d = NULL;
	struct replPropertyMetaData1 *rdn_m = NULL;
	struct dom_sid *sid = NULL;
	uint32_t rid = 0;
	uint32_t attr_count;
	int ret;

	if (!in->object.identifier) {
		return WERR_FOOBAR;
	}

	if (!in->object.identifier->dn || !in->object.identifier->dn[0]) {
		return WERR_FOOBAR;
	}

	if (in->object.attribute_ctr.num_attributes != 0 && !in->meta_data_ctr) {
		return WERR_FOOBAR;
	}

	if (in->object.attribute_ctr.num_attributes != in->meta_data_ctr->count) {
		return WERR_FOOBAR;
	}

	sid = &in->object.identifier->sid;
	if (sid->num_auths > 0) {
		rid = sid->sub_auths[sid->num_auths - 1];
	}

	msg = ldb_msg_new(mem_ctx);
	W_ERROR_HAVE_NO_MEMORY(msg);

	msg->dn			= ldb_dn_new(msg, ldb, in->object.identifier->dn);
	W_ERROR_HAVE_NO_MEMORY(msg->dn);

	msg->num_elements	= in->object.attribute_ctr.num_attributes;
	msg->elements		= talloc_array(msg, struct ldb_message_element,
					       msg->num_elements + 1); /* +1 because of the RDN attribute */
	W_ERROR_HAVE_NO_MEMORY(msg->elements);

	md = talloc(mem_ctx, struct replPropertyMetaDataBlob);
	W_ERROR_HAVE_NO_MEMORY(md);

	md->version		= 1;
	md->reserved		= 0;
	md->ctr.ctr1.count	= in->meta_data_ctr->count;
	md->ctr.ctr1.reserved	= 0;
	md->ctr.ctr1.array	= talloc_array(mem_ctx,
					       struct replPropertyMetaData1,
					       md->ctr.ctr1.count + 1); /* +1 because of the RDN attribute */
	W_ERROR_HAVE_NO_MEMORY(md->ctr.ctr1.array);

	for (i=0, attr_count=0; i < in->meta_data_ctr->count; i++, attr_count++) {
		struct drsuapi_DsReplicaAttribute *a;
		struct drsuapi_DsReplicaMetaData *d;
		struct replPropertyMetaData1 *m;
		struct ldb_message_element *e;
		uint32_t j;

		a = &in->object.attribute_ctr.attributes[i];
		d = &in->meta_data_ctr->meta_data[i];
		m = &md->ctr.ctr1.array[attr_count];
		e = &msg->elements[attr_count];

		if (dsdb_attid_in_list(ignore_attids, a->attid)) {
			attr_count--;
			continue;
		}

		if (GUID_all_zero(&d->originating_invocation_id)) {
			status = WERR_DS_SRC_GUID_MISMATCH;
			DEBUG(0, ("Refusing replication of object containing invalid zero invocationID on attribute %d of %s: %s\n",
				  a->attid,
				  ldb_dn_get_linearized(msg->dn),
				  win_errstr(status)));
			return status;
		}

		if (a->attid == DRSUAPI_ATTID_instanceType) {
			if (instanceType_e != NULL) {
				return WERR_FOOBAR;
			}
			instanceType_e = e;
		}

		for (j=0; j<a->value_ctr.num_values; j++) {
			status = drsuapi_decrypt_attribute(a->value_ctr.values[j].blob,
							   gensec_skey, rid,
							   dsdb_repl_flags, a);
			if (!W_ERROR_IS_OK(status)) {
				break;
			}
		}
		if (W_ERROR_EQUAL(status, WERR_TOO_MANY_SECRETS)) {
			WERROR get_name_status = dsdb_attribute_drsuapi_to_ldb(ldb, schema, pfm_remote,
									       a, msg->elements, e);
			if (W_ERROR_IS_OK(get_name_status)) {
				DEBUG(0, ("Unxpectedly got secret value %s on %s from DRS server\n",
					  e->name, ldb_dn_get_linearized(msg->dn)));
			} else {
				DEBUG(0, ("Unxpectedly got secret value on %s from DRS server",
					  ldb_dn_get_linearized(msg->dn)));
			}
		} else if (!W_ERROR_IS_OK(status)) {
			return status;
		}

		status = dsdb_attribute_drsuapi_to_ldb(ldb, schema, pfm_remote,
						       a, msg->elements, e);
		W_ERROR_NOT_OK_RETURN(status);

		m->attid			= a->attid;
		m->version			= d->version;
		m->originating_change_time	= d->originating_change_time;
		m->originating_invocation_id	= d->originating_invocation_id;
		m->originating_usn		= d->originating_usn;
		m->local_usn			= 0;

		if (d->originating_change_time > whenChanged) {
			whenChanged = d->originating_change_time;
		}

		if (a->attid == DRSUAPI_ATTID_name) {
			name_a = a;
			name_d = d;
		}
	}

	msg->num_elements = attr_count;
	md->ctr.ctr1.count = attr_count;
	if (name_a) {
		rdn_m = &md->ctr.ctr1.array[md->ctr.ctr1.count];
	}

	if (rdn_m) {
		struct ldb_message_element *el;
		const char *rdn_name = NULL;
		const struct ldb_val *rdn_value = NULL;
		const struct dsdb_attribute *rdn_attr = NULL;
		uint32_t rdn_attid;

		/*
		 * We only need the schema calls for the RDN in this
		 * codepath, and by doing this we avoid needing to
		 * have the dsdb_attribute_by_lDAPDisplayName accessor
		 * working during the schema load.
		 */
		rdn_name	= ldb_dn_get_rdn_name(msg->dn);
		rdn_attr	= dsdb_attribute_by_lDAPDisplayName(schema, rdn_name);
		if (!rdn_attr) {
			return WERR_FOOBAR;
		}
		rdn_attid	= rdn_attr->attributeID_id;
		rdn_value	= ldb_dn_get_rdn_val(msg->dn);

		el = ldb_msg_find_element(msg, rdn_attr->lDAPDisplayName);
		if (!el) {
			ret = ldb_msg_add_value(msg, rdn_attr->lDAPDisplayName, rdn_value, NULL);
			if (ret != LDB_SUCCESS) {
				return WERR_FOOBAR;
			}
		} else {
			if (el->num_values != 1) {
				DEBUG(0,(__location__ ": Unexpected num_values=%u\n",
					 el->num_values));
				return WERR_FOOBAR;				
			}
			if (!ldb_val_equal_exact(&el->values[0], rdn_value)) {
				DEBUG(0,(__location__ ": RDN value changed? '%*.*s' '%*.*s'\n",
					 (int)el->values[0].length, (int)el->values[0].length, el->values[0].data,
					 (int)rdn_value->length, (int)rdn_value->length, rdn_value->data));
				return WERR_FOOBAR;				
			}
		}

		rdn_m->attid				= rdn_attid;
		rdn_m->version				= name_d->version;
		rdn_m->originating_change_time		= name_d->originating_change_time;
		rdn_m->originating_invocation_id	= name_d->originating_invocation_id;
		rdn_m->originating_usn			= name_d->originating_usn;
		rdn_m->local_usn			= 0;
		md->ctr.ctr1.count++;

	}

	if (instanceType_e == NULL) {
		return WERR_FOOBAR;
	}

	instanceType = ldb_msg_find_attr_as_int(msg, "instanceType", 0);
	if (dsdb_repl_flags & DSDB_REPL_FLAG_PARTIAL_REPLICA) {
		/* the instanceType type for partial_replica
		   replication is sent via DRS with TYPE_WRITE set, but
		   must be used on the client with TYPE_WRITE removed
		*/
		if (instanceType & INSTANCE_TYPE_WRITE) {
			/*
			 * Make sure we do not change the order
			 * of msg->elements!
			 *
			 * That's why we use
			 * instanceType_e->num_values = 0
			 * instead of
			 * ldb_msg_remove_attr(msg, "instanceType");
			 */
			struct ldb_message_element *e;

			e = ldb_msg_find_element(msg, "instanceType");
			if (e != instanceType_e) {
				DEBUG(0,("instanceType_e[%p] changed to e[%p]\n",
					 instanceType_e, e));
				return WERR_FOOBAR;
			}

			instanceType_e->num_values = 0;

			instanceType &= ~INSTANCE_TYPE_WRITE;
			if (ldb_msg_add_fmt(msg, "instanceType", "%d", instanceType) != LDB_SUCCESS) {
				return WERR_INTERNAL_ERROR;
			}
		}
	} else {
		if (!(instanceType & INSTANCE_TYPE_WRITE)) {
			DEBUG(0, ("Refusing to replicate %s from a read-only repilca into a read-write replica!\n",
				  ldb_dn_get_linearized(msg->dn)));
			return WERR_DS_DRA_SOURCE_IS_PARTIAL_REPLICA;
		}
	}

	whenChanged_t = nt_time_to_unix(whenChanged);
	whenChanged_s = ldb_timestring(msg, whenChanged_t);
	W_ERROR_HAVE_NO_MEMORY(whenChanged_s);

	nt_status = GUID_to_ndr_blob(&in->object.identifier->guid, msg, &guid_value);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return ntstatus_to_werror(nt_status);
	}

	if (in->parent_object_guid) {
		nt_status = GUID_to_ndr_blob(in->parent_object_guid, msg, &parent_guid_value);
		if (!NT_STATUS_IS_OK(nt_status)) {
			return ntstatus_to_werror(nt_status);
		}
	} else {
		parent_guid_value = data_blob_null;
	}

	out->msg		= msg;
	out->guid_value		= guid_value;
	out->parent_guid_value	= parent_guid_value;
	out->when_changed	= whenChanged_s;
	out->meta_data		= md;
	return WERR_OK;
}
Exemplo n.º 13
0
static errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx)
{
    TALLOC_CTX *tmp_ctx = NULL;
    struct sss_domain_info *dom = dctx->domain;
    struct sudo_cmd_ctx *cmd_ctx = dctx->cmd_ctx;
    struct cli_ctx *cli_ctx = dctx->cmd_ctx->cli_ctx;
    struct ldb_result *user;
    time_t cache_expire = 0;
    struct tevent_req *dpreq;
    struct dp_callback_ctx *cb_ctx;
    const char *original_name = NULL;
    char *name = NULL;
    uid_t uid = 0;
    errno_t ret;

    tmp_ctx = talloc_new(NULL);
    if (tmp_ctx == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
        return ENOMEM;
    }

    while (dom) {
       /* if it is a domainless search, skip domains that require fully
        * qualified names instead */
        while (dom && cmd_ctx->check_next && dom->fqnames) {
            dom = get_next_domain(dom, false);
        }

        if (!dom) break;

        /* make sure to update the dctx if we changed domain */
        dctx->domain = dom;

        talloc_free(name);
        name = sss_get_cased_name(tmp_ctx, cmd_ctx->username,
                                  dom->case_sensitive);
        if (name == NULL) {
            DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory\n"));
            ret = ENOMEM;
            goto done;
        }

        DEBUG(SSSDBG_FUNC_DATA, ("Requesting info about [%s@%s]\n",
              name, dom->name));

        ret = sysdb_getpwnam(dctx, dctx->domain->sysdb,
                             dctx->domain, name, &user);
        if (ret != EOK) {
            DEBUG(SSSDBG_OP_FAILURE,
                  ("Failed to make request to our cache!\n"));
            ret = EIO;
            goto done;
        }

        if (user->count > 1) {
            DEBUG(SSSDBG_CRIT_FAILURE,
                  ("getpwnam call returned more than one result !?!\n"));
            ret = EIO;
            goto done;
        }

        if (user->count == 0 && !dctx->check_provider) {
            /* if a multidomain search, try with next */
            if (cmd_ctx->check_next) {
                dctx->check_provider = true;
                dom = get_next_domain(dom, false);
                if (dom) continue;
            }

            DEBUG(SSSDBG_MINOR_FAILURE, ("No results for getpwnam call\n"));
            ret = ENOENT;
            goto done;
        }

        /* One result found, check cache expiry */
        if (user->count == 1) {
            cache_expire = ldb_msg_find_attr_as_uint64(user->msgs[0],
                                                       SYSDB_CACHE_EXPIRE, 0);
        }

        /* If cache miss and we haven't checked DP yet OR the entry is
         * outdated, go to DP */
        if ((user->count == 0 || cache_expire < time(NULL))
            && dctx->check_provider) {
            dpreq = sss_dp_get_account_send(cli_ctx, cli_ctx->rctx,
                                            dom, false, SSS_DP_INITGROUPS,
                                            cmd_ctx->username, 0, NULL);
            if (!dpreq) {
                DEBUG(SSSDBG_CRIT_FAILURE,
                      ("Out of memory sending data provider request\n"));
                ret = ENOMEM;
                goto done;
            }

            cb_ctx = talloc_zero(cli_ctx, struct dp_callback_ctx);
            if(!cb_ctx) {
                talloc_zfree(dpreq);
                ret = ENOMEM;
                goto done;
            }

            cb_ctx->callback = sudosrv_check_user_dp_callback;
            cb_ctx->ptr = dctx;
            cb_ctx->cctx = cli_ctx;
            cb_ctx->mem_ctx = cli_ctx;

            tevent_req_set_callback(dpreq, sudosrv_dp_send_acct_req_done, cb_ctx);

            /* tell caller we are in an async call */
            ret = EAGAIN;
            goto done;
        }

        /* check uid */
        uid = ldb_msg_find_attr_as_int(user->msgs[0], SYSDB_UIDNUM, 0);
        if (uid != cmd_ctx->uid) {
            /* if a multidomain search, try with next */
            if (cmd_ctx->check_next) {
                dctx->check_provider = true;
                dom = get_next_domain(dom, false);
                if (dom) continue;
            }

            DEBUG(SSSDBG_MINOR_FAILURE, ("UID does not match\n"));
            ret = ENOENT;
            goto done;
        }

        /* user is stored in cache, remember cased and original name */
        original_name = ldb_msg_find_attr_as_string(user->msgs[0],
                                                    SYSDB_NAME, NULL);
        if (original_name == NULL) {
            DEBUG(SSSDBG_CRIT_FAILURE, ("A user with no name?\n"));
            ret = EFAULT;
            goto done;
        }

        cmd_ctx->cased_username = talloc_move(cmd_ctx, &name);
        cmd_ctx->orig_username = talloc_strdup(cmd_ctx, original_name);
        if (cmd_ctx->orig_username == NULL) {
            DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory\n"));
            ret = ENOMEM;
            goto done;
        }

        /* and set domain */
        cmd_ctx->domain = dom;

        DEBUG(SSSDBG_TRACE_FUNC, ("Returning info for user [%s@%s]\n",
              cmd_ctx->username, dctx->domain->name));
        ret = EOK;
        goto done;
    }
Exemplo n.º 14
0
/**
 * Retrieve the domain SID from the secrets database.
 * @return pointer to a SID object if the SID could be obtained, NULL otherwise
 */
struct dom_sid *secrets_get_domain_sid(TALLOC_CTX *mem_ctx,
				       struct loadparm_context *lp_ctx,
				       const char *domain,
				       enum netr_SchannelType *sec_channel_type,
				       char **errstring)
{
	struct ldb_context *ldb;
	struct ldb_message *msg;
	int ldb_ret;
	const char *attrs[] = { "objectSid", "secureChannelType", NULL };
	struct dom_sid *result = NULL;
	const struct ldb_val *v;
	enum ndr_err_code ndr_err;

	*errstring = NULL;

	ldb = secrets_db_connect(mem_ctx, lp_ctx);
	if (ldb == NULL) {
		DEBUG(5, ("secrets_db_connect failed\n"));
		return NULL;
	}

	ldb_ret = dsdb_search_one(ldb, ldb, &msg,
			      ldb_dn_new(mem_ctx, ldb, SECRETS_PRIMARY_DOMAIN_DN),
			      LDB_SCOPE_ONELEVEL,
			      attrs, 0, SECRETS_PRIMARY_DOMAIN_FILTER, domain);

	if (ldb_ret != LDB_SUCCESS) {
		*errstring = talloc_asprintf(mem_ctx, "Failed to find record for %s in %s: %s: %s", 
					     domain, (char *) ldb_get_opaque(ldb, "ldb_url"),
					     ldb_strerror(ldb_ret), ldb_errstring(ldb));
		return NULL;
	}
	v = ldb_msg_find_ldb_val(msg, "objectSid");
	if (v == NULL) {
		*errstring = talloc_asprintf(mem_ctx, "Failed to find a SID on record for %s in %s", 
					     domain, (char *) ldb_get_opaque(ldb, "ldb_url"));
		return NULL;
	}

	if (sec_channel_type) {
		int t;
		t = ldb_msg_find_attr_as_int(msg, "secureChannelType", -1);
		if (t == -1) {
			*errstring = talloc_asprintf(mem_ctx, "Failed to find secureChannelType for %s in %s",
						     domain, (char *) ldb_get_opaque(ldb, "ldb_url"));
			return NULL;
		}
		*sec_channel_type = t;
	}

	result = talloc(mem_ctx, struct dom_sid);
	if (result == NULL) {
		talloc_free(ldb);
		return NULL;
	}

	ndr_err = ndr_pull_struct_blob(v, result, result,
				       (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		*errstring = talloc_asprintf(mem_ctx, "Failed to parse SID on record for %s in %s", 
					     domain, (char *) ldb_get_opaque(ldb, "ldb_url"));
		talloc_free(result);
		talloc_free(ldb);
		return NULL;
	}

	return result;
}
Exemplo n.º 15
0
/**
 * Fill in credentials for the machine trust account, from the secrets database.
 *
 * @param cred Credentials structure to fill in
 * @retval NTSTATUS error detailing any failure
 */
static NTSTATUS cli_credentials_set_secrets_lct(struct cli_credentials *cred,
						struct loadparm_context *lp_ctx,
						struct ldb_context *ldb,
						const char *base,
						const char *filter,
						time_t secrets_tdb_last_change_time,
						const char *secrets_tdb_password,
						char **error_string)
{
	TALLOC_CTX *mem_ctx;

	int ldb_ret;
	struct ldb_message *msg;

	const char *machine_account;
	const char *password;
	const char *domain;
	const char *realm;
	enum netr_SchannelType sct;
	const char *salt_principal;
	char *keytab;
	const struct ldb_val *whenChanged;
	time_t lct;

	/* ok, we are going to get it now, don't recurse back here */
	cred->machine_account_pending = false;

	/* some other parts of the system will key off this */
	cred->machine_account = true;

	mem_ctx = talloc_named(cred, 0, "cli_credentials_set_secrets from ldb");

	if (!ldb) {
		/* Local secrets are stored in secrets.ldb */
		ldb = secrets_db_connect(mem_ctx, lp_ctx);
		if (!ldb) {
			*error_string = talloc_strdup(cred, "Could not open secrets.ldb");
			talloc_free(mem_ctx);
			return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
		}
	}

	ldb_ret = dsdb_search_one(ldb, mem_ctx, &msg,
				  ldb_dn_new(mem_ctx, ldb, base),
				  LDB_SCOPE_SUBTREE,
				  NULL, 0, "%s", filter);

	if (ldb_ret != LDB_SUCCESS) {
		*error_string = talloc_asprintf(cred, "Could not find entry to match filter: '%s' base: '%s': %s: %s",
						filter, base ? base : "",
						ldb_strerror(ldb_ret), ldb_errstring(ldb));
		talloc_free(mem_ctx);
		return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
	}

	password = ldb_msg_find_attr_as_string(msg, "secret", NULL);

	whenChanged = ldb_msg_find_ldb_val(msg, "whenChanged");
	if (!whenChanged || ldb_val_to_time(whenChanged, &lct) != LDB_SUCCESS) {
		/* This attribute is mandetory */
		talloc_free(mem_ctx);
		return NT_STATUS_NOT_FOUND;
	}

	/* Don't set secrets.ldb info if the secrets.tdb entry was more recent */
	if (lct < secrets_tdb_last_change_time) {
		talloc_free(mem_ctx);
		return NT_STATUS_NOT_FOUND;
	}

	if (lct == secrets_tdb_last_change_time && secrets_tdb_password && strcmp(password, secrets_tdb_password) != 0) {
		talloc_free(mem_ctx);
		return NT_STATUS_NOT_FOUND;
	}

	cli_credentials_set_password_last_changed_time(cred, lct);

	machine_account = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);

	if (!machine_account) {
		machine_account = ldb_msg_find_attr_as_string(msg, "servicePrincipalName", NULL);

		if (!machine_account) {
			const char *ldap_bind_dn = ldb_msg_find_attr_as_string(msg, "ldapBindDn", NULL);
			if (!ldap_bind_dn) {
				*error_string = talloc_asprintf(cred,
								"Could not find 'samAccountName', "
								"'servicePrincipalName' or "
								"'ldapBindDn' in secrets record: %s",
								ldb_dn_get_linearized(msg->dn));
				talloc_free(mem_ctx);
				return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
			} else {
				/* store bind dn in credentials */
				cli_credentials_set_bind_dn(cred, ldap_bind_dn);
			}
		}
	}

	salt_principal = ldb_msg_find_attr_as_string(msg, "saltPrincipal", NULL);
	cli_credentials_set_salt_principal(cred, salt_principal);

	sct = ldb_msg_find_attr_as_int(msg, "secureChannelType", 0);
	if (sct) {
		cli_credentials_set_secure_channel_type(cred, sct);
	}

	if (!password) {
		const struct ldb_val *nt_password_hash = ldb_msg_find_ldb_val(msg, "unicodePwd");
		struct samr_Password hash;
		ZERO_STRUCT(hash);
		if (nt_password_hash) {
			memcpy(hash.hash, nt_password_hash->data,
			       MIN(nt_password_hash->length, sizeof(hash.hash)));

			cli_credentials_set_nt_hash(cred, &hash, CRED_SPECIFIED);
		} else {
			cli_credentials_set_password(cred, NULL, CRED_SPECIFIED);
		}
	} else {
		cli_credentials_set_password(cred, password, CRED_SPECIFIED);
	}

	domain = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
	if (domain) {
		cli_credentials_set_domain(cred, domain, CRED_SPECIFIED);
	}

	realm = ldb_msg_find_attr_as_string(msg, "realm", NULL);
	if (realm) {
		cli_credentials_set_realm(cred, realm, CRED_SPECIFIED);
	}

	if (machine_account) {
		cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED);
	}

	cli_credentials_set_kvno(cred, ldb_msg_find_attr_as_int(msg, "msDS-KeyVersionNumber", 0));

	/* If there was an external keytab specified by reference in
	 * the LDB, then use this.  Otherwise we will make one up
	 * (chewing CPU time) from the password */
	keytab = keytab_name_from_msg(cred, ldb, msg);
	if (keytab) {
		cli_credentials_set_keytab_name(cred, lp_ctx, keytab, CRED_SPECIFIED);
		talloc_free(keytab);
	}
	talloc_free(mem_ctx);

	return NT_STATUS_OK;
}
Exemplo n.º 16
0
/* allocate a RID using our RID Set
   If we run out of RIDs then allocate a new pool
   either locally or by contacting the RID Manager
*/
int ridalloc_allocate_rid(struct ldb_module *module, uint32_t *rid)
{
	struct ldb_context *ldb;
	static const char * const attrs[] = { "rIDAllocationPool", "rIDPreviousAllocationPool",
					      "rIDNextRID" , "rIDUsedPool", NULL };
	int ret;
	struct ldb_dn *rid_set_dn;
	struct ldb_result *res;
	uint64_t alloc_pool, prev_alloc_pool;
	uint32_t prev_alloc_pool_lo, prev_alloc_pool_hi;
	uint32_t rid_used_pool;
	int prev_rid;
	TALLOC_CTX *tmp_ctx = talloc_new(module);

	(*rid) = 0;
	ldb = ldb_module_get_ctx(module);

	ret = samdb_rid_set_dn(ldb, tmp_ctx, &rid_set_dn);
	if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
		ret = ridalloc_create_own_rid_set(module, tmp_ctx, &rid_set_dn);
	}
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, __location__ ": No RID Set DN - %s",
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn, attrs, 0);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
				       ldb_dn_get_linearized(rid_set_dn));
		talloc_free(tmp_ctx);
		return ret;
	}

	prev_alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDPreviousAllocationPool", 0);
	alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAllocationPool", 0);
	prev_rid = ldb_msg_find_attr_as_int(res->msgs[0], "rIDNextRID", 0);
	rid_used_pool = ldb_msg_find_attr_as_int(res->msgs[0], "rIDUsedPool", 0);
	if (alloc_pool == 0) {
		ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
				       ldb_dn_get_linearized(rid_set_dn));
		talloc_free(tmp_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	prev_alloc_pool_lo = prev_alloc_pool & 0xFFFFFFFF;
	prev_alloc_pool_hi = prev_alloc_pool >> 32;
	if (prev_rid >= prev_alloc_pool_hi) {
		if (prev_alloc_pool == 0) {
			ret = dsdb_module_set_integer(module, rid_set_dn, "rIDPreviousAllocationPool", alloc_pool);
		} else {
			ret = dsdb_module_constrainted_update_integer(module, rid_set_dn, "rIDPreviousAllocationPool",
								      prev_alloc_pool, alloc_pool);
		}
		if (ret != LDB_SUCCESS) {
			ldb_asprintf_errstring(ldb, __location__ ": Failed to update rIDPreviousAllocationPool on %s - %s",
					       ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
			talloc_free(tmp_ctx);
			return ret;
		}
		prev_alloc_pool = alloc_pool;
		prev_alloc_pool_lo = prev_alloc_pool & 0xFFFFFFFF;
		prev_alloc_pool_hi = prev_alloc_pool >> 32;

		/* update the rIDUsedPool attribute */
		ret = dsdb_module_set_integer(module, rid_set_dn, "rIDUsedPool", rid_used_pool+1);
		if (ret != LDB_SUCCESS) {
			ldb_asprintf_errstring(ldb, __location__ ": Failed to update rIDUsedPool on %s - %s",
					       ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
			talloc_free(tmp_ctx);
			return ret;
		}

		(*rid) = prev_alloc_pool_lo;
	}

	/* see if we are still out of RIDs, and if so then ask
	   the RID Manager to give us more */
	if (prev_rid >= prev_alloc_pool_hi) {
		uint64_t new_pool;
		ret = ridalloc_refresh_own_pool(module, &new_pool);
		if (ret != LDB_SUCCESS) {
			return ret;
		}
		ret = dsdb_module_constrainted_update_integer(module, rid_set_dn, "rIDPreviousAllocationPool",
							      prev_alloc_pool, new_pool);
		if (ret != LDB_SUCCESS) {
			ldb_asprintf_errstring(ldb, __location__ ": Failed to update rIDPreviousAllocationPool on %s - %s",
					       ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
			talloc_free(tmp_ctx);
			return ret;
		}
		prev_alloc_pool = new_pool;
		prev_alloc_pool_lo = prev_alloc_pool & 0xFFFFFFFF;
		prev_alloc_pool_hi = prev_alloc_pool >> 32;
		(*rid) = prev_alloc_pool_lo;
	} else {