Esempio n. 1
0
/* Hook to allow GENSEC to handle blob-based authentication
 * mechanisms, without directly linking the mechansim code */
static NTSTATUS prepare_gensec(TALLOC_CTX *mem_ctx,
			       struct gensec_security **gensec_context)
{
	NTSTATUS status;
	struct loadparm_context *lp_ctx;
	struct tevent_context *event_ctx;
	TALLOC_CTX *frame = talloc_stackframe();
	struct gensec_security *gensec_ctx;
	struct imessaging_context *msg_ctx;
	struct cli_credentials *server_credentials;

	lp_ctx = loadparm_init_s3(frame, loadparm_s3_context());
	if (lp_ctx == NULL) {
		DEBUG(1, ("loadparm_init_s3 failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}
	event_ctx = s4_event_context_init(mem_ctx);
	if (event_ctx == NULL) {
		DEBUG(1, ("s4_event_context_init failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	msg_ctx = imessaging_client_init(frame,
					 lpcfg_imessaging_path(frame, lp_ctx),
					 event_ctx);
	if (msg_ctx == NULL) {
		DEBUG(1, ("imessaging_init failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	server_credentials
		= cli_credentials_init(frame);
	if (!server_credentials) {
		DEBUG(1, ("Failed to init server credentials"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	cli_credentials_set_conf(server_credentials, lp_ctx);
	status = cli_credentials_set_machine_account(server_credentials, lp_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("Failed to obtain server credentials, perhaps a standalone server?: %s\n", nt_errstr(status)));
		talloc_free(server_credentials);
		server_credentials = NULL;
	}

	status = samba_server_gensec_start(mem_ctx,
					   event_ctx, msg_ctx,
					   lp_ctx, server_credentials, "cifs",
					   &gensec_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status)));
		TALLOC_FREE(frame);
		return status;
	}

	talloc_reparent(frame, gensec_ctx, msg_ctx);
	talloc_reparent(frame, gensec_ctx, event_ctx);
	talloc_reparent(frame, gensec_ctx, lp_ctx);
	talloc_reparent(frame, gensec_ctx, server_credentials);

	gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SESSION_KEY);
	gensec_want_feature(gensec_ctx, GENSEC_FEATURE_UNIX_TOKEN);

	*gensec_context = gensec_ctx;
	TALLOC_FREE(frame);
	return status;
}
Esempio n. 2
0
/* Return the members of this group (which may be a domain group or an alias) */
NTSTATUS dsdb_enum_group_mem(struct ldb_context *ldb,
			     TALLOC_CTX *mem_ctx,
			     struct ldb_dn *dn,
			     struct dom_sid **members_out,
			     unsigned int *pnum_members)
{
	struct ldb_message *msg;
	unsigned int i, j;
	int ret;
	struct dom_sid *members;
	struct ldb_message_element *member_el;
	const char *attrs[] = { "member", NULL };
	NTSTATUS status;
	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);

	ret = dsdb_search_one(ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs,
			      DSDB_SEARCH_SHOW_EXTENDED_DN, NULL);
	if (ret == LDB_ERR_NO_SUCH_OBJECT) {
		talloc_free(tmp_ctx);
		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
	}
	if (ret != LDB_SUCCESS) {
		DEBUG(1, ("dsdb_enum_group_mem: dsdb_search for %s failed: %s\n",
			  ldb_dn_get_linearized(dn), ldb_errstring(ldb)));
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	member_el = ldb_msg_find_element(msg, "member");
	if (!member_el) {
		*members_out = NULL;
		*pnum_members = 0;
		talloc_free(tmp_ctx);
		return NT_STATUS_OK;
	}

	members = talloc_array(mem_ctx, struct dom_sid, member_el->num_values);
	if (members == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	j = 0;
	for (i=0; i <member_el->num_values; i++) {
		struct ldb_dn *member_dn = ldb_dn_from_ldb_val(tmp_ctx, ldb,
							       &member_el->values[i]);
		if (!member_dn || !ldb_dn_validate(member_dn)) {
			DEBUG(1, ("Could not parse %*.*s as a DN\n",
				  (int)member_el->values[i].length,
				  (int)member_el->values[i].length,
				  (const char *)member_el->values[i].data));
			talloc_free(tmp_ctx);
			return NT_STATUS_INTERNAL_DB_CORRUPTION;
		}

		status = dsdb_get_extended_dn_sid(member_dn, &members[j],
						  "SID");
		if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
			/* If we fail finding a SID then this is no error since
			 * it could be a non SAM object - e.g. a contact */
			continue;
		} else if (!NT_STATUS_IS_OK(status)) {
			DEBUG(1, ("When parsing DN '%s' we failed to parse it's SID component, so we cannot fetch the membership: %s\n",
				  ldb_dn_get_extended_linearized(tmp_ctx, member_dn, 1),
				  nt_errstr(status)));
			talloc_free(tmp_ctx);
			return status;
		}

		++j;
	}

	*members_out = talloc_steal(mem_ctx, members);
	*pnum_members = j;
	talloc_free(tmp_ctx);
	return NT_STATUS_OK;
}
Esempio n. 3
0
NTSTATUS sec_access_check_ds(const struct security_descriptor *sd,
			     const struct security_token *token,
			     uint32_t access_desired,
			     uint32_t *access_granted,
			     struct object_tree *tree,
			     struct dom_sid *replace_sid)
{
        uint32_t i;
        uint32_t bits_remaining;
        struct object_tree *node;
        const struct GUID *type;
        struct dom_sid *ps_sid = dom_sid_parse_talloc(NULL, SID_NT_SELF);

        *access_granted = access_desired;
        bits_remaining = access_desired;

        /* handle the maximum allowed flag */
        if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) {
                access_desired |= access_check_max_allowed(sd, token);
                access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED;
                *access_granted = access_desired;
		bits_remaining = access_desired;
        }

        if (access_desired & SEC_FLAG_SYSTEM_SECURITY) {
                if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) {
                        bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY;
                } else {
                        talloc_free(ps_sid);
                        return NT_STATUS_PRIVILEGE_NOT_HELD;
                }
        }

	/* the owner always gets SEC_STD_WRITE_DAC and SEC_STD_READ_CONTROL */
	if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL)) &&
	    security_token_has_sid(token, sd->owner_sid)) {
		bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL);
	}

	/* TODO: remove this, as it is file server specific */
	if ((bits_remaining & SEC_RIGHTS_PRIV_RESTORE) &&
	    security_token_has_privilege(token, SEC_PRIV_RESTORE)) {
		bits_remaining &= ~(SEC_RIGHTS_PRIV_RESTORE);
	}
	if ((bits_remaining & SEC_RIGHTS_PRIV_BACKUP) &&
	    security_token_has_privilege(token, SEC_PRIV_BACKUP)) {
		bits_remaining &= ~(SEC_RIGHTS_PRIV_BACKUP);
	}

        /* a NULL dacl allows access */
        if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) {
                *access_granted = access_desired;
                talloc_free(ps_sid);
                return NT_STATUS_OK;
        }

        if (sd->dacl == NULL) {
                goto done;
        }

        /* check each ace in turn. */
        for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) {
		struct dom_sid *trustee;
		struct security_ace *ace = &sd->dacl->aces[i];

                if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) {
                        continue;
                }
		if (dom_sid_equal(&ace->trustee, ps_sid) && replace_sid) {
			trustee = replace_sid;
		}
		else
		{
			trustee = &ace->trustee;
		}
                if (!security_token_has_sid(token, trustee)) {
                        continue;
                }

                switch (ace->type) {
                case SEC_ACE_TYPE_ACCESS_ALLOWED:
                        if (tree)
                                object_tree_modify_access(tree, ace->access_mask);

                        bits_remaining &= ~ace->access_mask;
                        break;
                case SEC_ACE_TYPE_ACCESS_DENIED:
                        if (bits_remaining & ace->access_mask) {
                                talloc_free(ps_sid);
                                return NT_STATUS_ACCESS_DENIED;
                        }
                        break;
                case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT:
                case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT:
                        /* check only in case we have provided a tree,
                         * the ACE has an object type and that type
                         * is in the tree                           */
                        type = get_ace_object_type(ace);

                        if (!tree)
                                continue;

                        if (!type)
                                node = tree;
                        else
                                if (!(node = get_object_tree_by_GUID(tree, type)))
                                        continue;

                        if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT) {
                                object_tree_modify_access(node, ace->access_mask);
                                if (node->remaining_access == 0) {
                                        talloc_free(ps_sid);
                                        return NT_STATUS_OK;
                                }
                        } else {
                                if (node->remaining_access & ace->access_mask){
                                        talloc_free(ps_sid);
                                        return NT_STATUS_ACCESS_DENIED;
                                }
                        }
                        break;
                default:        /* Other ACE types not handled/supported */
                        break;
                }
        }

done:
        talloc_free(ps_sid);
        if (bits_remaining != 0) {
                return NT_STATUS_ACCESS_DENIED;
        }

        return NT_STATUS_OK;
}
Esempio n. 4
0
bool torture_samba3_checkfsp(struct torture_context *torture)
{
	struct smbcli_state *cli;
	const char *fname = "test.txt";
	const char *dirname = "testdir";
	int fnum;
	NTSTATUS status;
	bool ret = true;
	TALLOC_CTX *mem_ctx;
	ssize_t nread;
	char buf[16];
	struct smbcli_tree *tree2;

	if ((mem_ctx = talloc_init("torture_samba3_checkfsp")) == NULL) {
		d_printf("talloc_init failed\n");
		return false;
	}

	if (!torture_open_connection_share(
		    torture, &cli, torture, torture_setting_string(torture, "host", NULL),
		    torture_setting_string(torture, "share", NULL), torture->ev)) {
		d_printf("torture_open_connection_share failed\n");
		ret = false;
		goto done;
	}

	smbcli_deltree(cli->tree, dirname);

	status = torture_second_tcon(torture, cli->session,
				     torture_setting_string(torture, "share", NULL),
				     &tree2);
	CHECK_STATUS(status, NT_STATUS_OK);
	if (!NT_STATUS_IS_OK(status))
		goto done;

	/* Try a read on an invalid FID */

	nread = smbcli_read(cli->tree, 4711, buf, 0, sizeof(buf));
	CHECK_STATUS(smbcli_nt_error(cli->tree), NT_STATUS_INVALID_HANDLE);

	/* Try a read on a directory handle */

	status = smbcli_mkdir(cli->tree, dirname);
	if (!NT_STATUS_IS_OK(status)) {
		d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status));
		ret = false;
		goto done;
	}

	/* Open the directory */
	{
		union smb_open io;
		io.generic.level = RAW_OPEN_NTCREATEX;
		io.ntcreatex.in.flags = NTCREATEX_FLAGS_EXTENDED;
		io.ntcreatex.in.root_fid = 0;
		io.ntcreatex.in.security_flags = 0;
		io.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
		io.ntcreatex.in.access_mask = SEC_RIGHTS_FILE_ALL;
		io.ntcreatex.in.alloc_size = 0;
		io.ntcreatex.in.file_attr = FILE_ATTRIBUTE_DIRECTORY;
		io.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
		io.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
		io.ntcreatex.in.create_options = 0;
		io.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
		io.ntcreatex.in.fname = dirname;
		status = smb_raw_open(cli->tree, mem_ctx, &io);
		if (!NT_STATUS_IS_OK(status)) {
			d_printf("smb_open on the directory failed: %s\n",
				 nt_errstr(status));
			ret = false;
			goto done;
		}
		fnum = io.ntcreatex.out.file.fnum;
	}

	/* Try a read on the directory */

	nread = smbcli_read(cli->tree, fnum, buf, 0, sizeof(buf));
	if (nread >= 0) {
		d_printf("smbcli_read on a directory succeeded, expected "
			 "failure\n");
		ret = false;
	}

	CHECK_STATUS(smbcli_nt_error(cli->tree),
		     NT_STATUS_INVALID_DEVICE_REQUEST);

	/* Same test on the second tcon */

	nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf));
	if (nread >= 0) {
		d_printf("smbcli_read on a directory succeeded, expected "
			 "failure\n");
		ret = false;
	}

	CHECK_STATUS(smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE);

	smbcli_close(cli->tree, fnum);

	/* Try a normal file read on a second tcon */

	fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
	if (fnum == -1) {
		d_printf("Failed to create %s - %s\n", fname,
			 smbcli_errstr(cli->tree));
		ret = false;
		goto done;
	}

	nread = smbcli_read(tree2, fnum, buf, 0, sizeof(buf));
	CHECK_STATUS(smbcli_nt_error(tree2), NT_STATUS_INVALID_HANDLE);

	smbcli_close(cli->tree, fnum);

 done:
	smbcli_deltree(cli->tree, dirname);
	torture_close_connection(cli);
	talloc_free(mem_ctx);

	return ret;
}
Esempio n. 5
0
/* Add a user, SAMR style, including the correct transaction
 * semantics.  Used by the SAMR server and by pdb_samba4 */
NTSTATUS dsdb_add_user(struct ldb_context *ldb,
		       TALLOC_CTX *mem_ctx,
		       const char *account_name,
		       uint32_t acct_flags,
		       const struct dom_sid *forced_sid,
		       struct dom_sid **sid,
		       struct ldb_dn **dn)
{
	const char *name;
	struct ldb_message *msg;
	int ret;
	const char *container, *obj_class=NULL;
	char *cn_name;
	size_t cn_name_len;

	const char *attrs[] = {
		"objectSid",
		"userAccountControl",
		NULL
	};

	uint32_t user_account_control;
	struct ldb_dn *account_dn;
	struct dom_sid *account_sid;

	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);

	/*
	 * Start a transaction, so we can query and do a subsequent atomic
	 * modify
	 */

	ret = ldb_transaction_start(ldb);
	if (ret != LDB_SUCCESS) {
		DEBUG(0,("Failed to start a transaction for user creation: %s\n",
			 ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return NT_STATUS_LOCK_NOT_GRANTED;
	}

	/* check if the user already exists */
	name = samdb_search_string(ldb, tmp_ctx, NULL,
				   "sAMAccountName",
				   "(&(sAMAccountName=%s)(objectclass=user))",
				   ldb_binary_encode_string(tmp_ctx, account_name));
	if (name != NULL) {
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);
		return NT_STATUS_USER_EXISTS;
	}

	cn_name = talloc_strdup(tmp_ctx, account_name);
	if (!cn_name) {
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	cn_name_len = strlen(cn_name);
	if (cn_name_len < 1) {
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	}

	msg = ldb_msg_new(tmp_ctx);
	if (msg == NULL) {
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	/* This must be one of these values *only* */
	if (acct_flags == ACB_NORMAL) {
		container = "CN=Users";
		obj_class = "user";

	} else if (acct_flags == ACB_WSTRUST) {
		if (cn_name[cn_name_len - 1] != '$') {
			ldb_transaction_cancel(ldb);
			return NT_STATUS_FOOBAR;
		}
		cn_name[cn_name_len - 1] = '\0';
		container = "CN=Computers";
		obj_class = "computer";

	} else if (acct_flags == ACB_SVRTRUST) {
		if (cn_name[cn_name_len - 1] != '$') {
			ldb_transaction_cancel(ldb);
			return NT_STATUS_FOOBAR;
		}
		cn_name[cn_name_len - 1] = '\0';
		container = "OU=Domain Controllers";
		obj_class = "computer";
	} else if (acct_flags == ACB_DOMTRUST) {
		DEBUG(3, ("Invalid account flags specified:  cannot create domain trusts via this interface (must use LSA CreateTrustedDomain calls\n"));
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	} else {
		DEBUG(3, ("Invalid account flags specified 0x%08X, must be exactly one of \n"
			  "ACB_NORMAL (0x%08X) ACB_WSTRUST (0x%08X) or ACB_SVRTRUST (0x%08X)\n",
			  acct_flags,
			  ACB_NORMAL, ACB_WSTRUST, ACB_SVRTRUST));
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* add core elements to the ldb_message for the user */
	msg->dn = ldb_dn_copy(msg, ldb_get_default_basedn(ldb));
	if ( ! ldb_dn_add_child_fmt(msg->dn, "CN=%s,%s", cn_name, container)) {
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);
		return NT_STATUS_FOOBAR;
	}

	ldb_msg_add_string(msg, "sAMAccountName", account_name);
	ldb_msg_add_string(msg, "objectClass", obj_class);

	/* This is only here for migrations using pdb_samba4, the
	 * caller and the samldb are responsible for ensuring it makes
	 * sense */
	if (forced_sid) {
		ret = samdb_msg_add_dom_sid(ldb, msg, msg, "objectSID", forced_sid);
		if (ret != LDB_SUCCESS) {
			ldb_transaction_cancel(ldb);
			talloc_free(tmp_ctx);
			return NT_STATUS_INTERNAL_ERROR;
		}
	}

	/* create the user */
	ret = ldb_add(ldb, msg);
	switch (ret) {
	case LDB_SUCCESS:
		break;
	case LDB_ERR_ENTRY_ALREADY_EXISTS:
		ldb_transaction_cancel(ldb);
		DEBUG(0,("Failed to create user record %s: %s\n",
			 ldb_dn_get_linearized(msg->dn),
			 ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return NT_STATUS_USER_EXISTS;
	case LDB_ERR_UNWILLING_TO_PERFORM:
	case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
		ldb_transaction_cancel(ldb);
		DEBUG(0,("Failed to create user record %s: %s\n",
			 ldb_dn_get_linearized(msg->dn),
			 ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return NT_STATUS_ACCESS_DENIED;
	default:
		ldb_transaction_cancel(ldb);
		DEBUG(0,("Failed to create user record %s: %s\n",
			 ldb_dn_get_linearized(msg->dn),
			 ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	account_dn = msg->dn;

	/* retrieve the sid and account control bits for the user just created */
	ret = dsdb_search_one(ldb, tmp_ctx, &msg,
			      account_dn, LDB_SCOPE_BASE, attrs, 0, NULL);

	if (ret != LDB_SUCCESS) {
		ldb_transaction_cancel(ldb);
		DEBUG(0,("Can't locate the account we just created %s: %s\n",
			 ldb_dn_get_linearized(account_dn), ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}
	account_sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid");
	if (account_sid == NULL) {
		ldb_transaction_cancel(ldb);
		DEBUG(0,("Apparently we failed to get the objectSid of the just created account record %s\n",
			 ldb_dn_get_linearized(msg->dn)));
		talloc_free(tmp_ctx);
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	/* Change the account control to be the correct account type.
	 * The default is for a workstation account */
	user_account_control = ldb_msg_find_attr_as_uint(msg, "userAccountControl", 0);
	user_account_control = (user_account_control &
				~(UF_NORMAL_ACCOUNT |
				  UF_INTERDOMAIN_TRUST_ACCOUNT |
				  UF_WORKSTATION_TRUST_ACCOUNT |
				  UF_SERVER_TRUST_ACCOUNT));
	user_account_control |= ds_acb2uf(acct_flags);

	talloc_free(msg);
	msg = ldb_msg_new(tmp_ctx);
	if (msg == NULL) {
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	msg->dn = account_dn;

	if (samdb_msg_add_uint(ldb, tmp_ctx, msg,
			       "userAccountControl",
			       user_account_control) != LDB_SUCCESS) {
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	/* modify the samdb record */
	ret = dsdb_replace(ldb, msg, 0);
	if (ret != LDB_SUCCESS) {
		DEBUG(0,("Failed to modify account record %s to set userAccountControl: %s\n",
			 ldb_dn_get_linearized(msg->dn),
			 ldb_errstring(ldb)));
		ldb_transaction_cancel(ldb);
		talloc_free(tmp_ctx);

		/* we really need samdb.c to return NTSTATUS */
		return NT_STATUS_UNSUCCESSFUL;
	}

	ret = ldb_transaction_commit(ldb);
	if (ret != LDB_SUCCESS) {
		DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n",
			 ldb_dn_get_linearized(msg->dn),
			 ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}
	*dn = talloc_steal(mem_ctx, account_dn);
	if (sid) {
		*sid = talloc_steal(mem_ctx, account_sid);
	}
	talloc_free(tmp_ctx);
	return NT_STATUS_OK;
}
Esempio n. 6
0
static NTSTATUS sldb_set(struct share_context *ctx, const char *name, struct share_info *info, int count)
{
	struct ldb_context *ldb;
	struct ldb_message *msg;
	TALLOC_CTX *tmp_ctx;
	NTSTATUS ret;
	bool do_rename = false;
	char *newname;
	int err, i;

	if (!name) {
		return NT_STATUS_INVALID_PARAMETER;
	}
	
	tmp_ctx = talloc_new(NULL);
	if (!tmp_ctx) {
		DEBUG(0,("ERROR: Out of memory!\n"));
		return NT_STATUS_NO_MEMORY;
	}

	ldb = talloc_get_type(ctx->priv_data, struct ldb_context);

	msg = ldb_msg_new(tmp_ctx);
	if (!msg) {
		DEBUG(0,("ERROR: Out of memory!\n"));
		ret = NT_STATUS_NO_MEMORY;
		goto done;
	}

	/* TODO: escape name */
	msg->dn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s,CN=SHARES", name);
	if (!msg->dn) {
		DEBUG(0,("ERROR: Out of memory!\n"));
		ret = NT_STATUS_NO_MEMORY;
		goto done;
	}

	for (i = 0; i < count; i++) {
		if (strcasecmp(info[i].name, SHARE_NAME) == 0) {
			if (strcasecmp(name, (char *)info[i].value) != 0) {
				do_rename = true;
				newname = (char *)info[i].value;
				SHARE_MOD_STRING("cn", (char *)info[i].value);
			}
		}

		switch (info[i].type) {
		case SHARE_INFO_STRING:
			SHARE_MOD_STRING(info[i].name, (char *)info[i].value);
			break;
		case SHARE_INFO_INT:
			SHARE_MOD_INT(info[i].name, *((int *)info[i].value));
			break;
		case SHARE_INFO_BLOB:
			SHARE_MOD_BLOB(info[i].name, (DATA_BLOB *)info[i].value);
			break;
		default:
			DEBUG(2,("ERROR: Invalid share info type for %s\n", info[i].name));
			ret = NT_STATUS_INVALID_PARAMETER;
			goto done;
		}
	}

	if (do_rename) {
		struct ldb_dn *olddn, *newdn;

		olddn = msg->dn;

		/* TODO: escape newname */
		newdn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s,CN=SHARES", newname);
		if (!newdn) {
			DEBUG(0,("ERROR: Out of memory!\n"));
			ret = NT_STATUS_NO_MEMORY;
			goto done;
		}

		err = ldb_rename(ldb, olddn, newdn);
		if (err != LDB_SUCCESS) {
			DEBUG(2,("ERROR: unable to rename share %s (to %s)\n"
				 "       err=%d [%s]\n", name, newname, err, ldb_errstring(ldb)));
			if (err == LDB_ERR_NO_SUCH_OBJECT) {
				ret = NT_STATUS_OBJECT_NAME_COLLISION;
			} else {
				ret = NT_STATUS_UNSUCCESSFUL;
			}
			goto done;
		}

		msg->dn = newdn;
	}

	err = ldb_modify(ldb, msg);
	if (err != LDB_SUCCESS) {
		DEBUG(2,("ERROR: unable to add share %s to share.ldb\n"
			 "       err=%d [%s]\n", name, err, ldb_errstring(ldb)));
		if (err == LDB_ERR_NO_SUCH_OBJECT) {
			ret = NT_STATUS_OBJECT_NAME_COLLISION;
		} else {
			ret = NT_STATUS_UNSUCCESSFUL;
		}
		goto done;
	}

	ret = NT_STATUS_OK;
done:
	talloc_free(tmp_ctx);
	return ret;
}
Esempio n. 7
0
static NTSTATUS raw_smbcli_t2open(struct smbcli_tree *tree, const char *fname, int flags, int share_mode, int *fnum)
{
        union smb_open io;
        uint_t openfn=0;
        uint_t accessmode=0;
        TALLOC_CTX *mem_ctx;
        NTSTATUS status;

        mem_ctx = talloc_init("raw_t2open");
        if (!mem_ctx) return NT_STATUS_NO_MEMORY;

        if (flags & O_CREAT) {
                openfn |= OPENX_OPEN_FUNC_CREATE;
        }
        if (!(flags & O_EXCL)) {
                if (flags & O_TRUNC) {
                        openfn |= OPENX_OPEN_FUNC_TRUNC;
                } else {
                        openfn |= OPENX_OPEN_FUNC_OPEN;
                }
        }

        accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);

        if ((flags & O_ACCMODE) == O_RDWR) {
                accessmode |= OPENX_MODE_ACCESS_RDWR;
        } else if ((flags & O_ACCMODE) == O_WRONLY) {
                accessmode |= OPENX_MODE_ACCESS_WRITE;
        } else if ((flags & O_ACCMODE) == O_RDONLY) {
                accessmode |= OPENX_MODE_ACCESS_READ;
	}

#if defined(O_SYNC)
        if ((flags & O_SYNC) == O_SYNC) {
                accessmode |= OPENX_MODE_WRITE_THRU;
        }
#endif

        if (share_mode == DENY_FCB) {
                accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
        }

	memset(&io, '\0', sizeof(io));
        io.t2open.level = RAW_OPEN_T2OPEN;
        io.t2open.in.flags = 0;
        io.t2open.in.open_mode = accessmode;
        io.t2open.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
        io.t2open.in.file_attrs = 0;
        io.t2open.in.write_time = 0;
        io.t2open.in.open_func = openfn;
        io.t2open.in.size = 0;
        io.t2open.in.timeout = 0;
        io.t2open.in.fname = fname;

        io.t2open.in.num_eas = 1;
	io.t2open.in.eas = talloc_array(mem_ctx, struct ea_struct, io.t2open.in.num_eas);
	io.t2open.in.eas[0].flags = 0;
	io.t2open.in.eas[0].name.s = ".CLASSINFO";
	io.t2open.in.eas[0].value = data_blob_talloc(mem_ctx, "first value", 11);

        status = smb_raw_open(tree, mem_ctx, &io);
        talloc_free(mem_ctx);

        if (fnum && NT_STATUS_IS_OK(status)) {
                *fnum = io.openx.out.file.fnum;
        }

        return status;
}
Esempio n. 8
0
static char *xlat_aprint(TALLOC_CTX *ctx, REQUEST *request, xlat_exp_t const * const node,
			 RADIUS_ESCAPE_STRING escape, void *escape_ctx, int lvl)
{
	ssize_t rcode;
	char *str = NULL, *child;
	REQUEST *ref;

	XLAT_DEBUG("%.*sxlat aprint %d", lvl, xlat_spaces, node->type);

	switch (node->type) {
		/*
		 *	Don't escape this.
		 */
	case XLAT_LITERAL:
		return talloc_strdup(ctx, node->fmt);

		/*
		 *	Do a one-character expansion.
		 */
	case XLAT_PERCENT: {
		char const *p;
		char *nl;
		size_t freespace = 256;
		struct tm *TM, s_TM;
		time_t when;

		str = talloc_array(ctx, char, freespace); /* @todo do better allocation */
		p = node->fmt;

		when = request->timestamp;
		if (request->packet) {
			when = request->packet->timestamp.tv_sec;
		}
		
		switch (*p) {
		case '%':
			str[0] = '%';
			str[1] = '\0';
			break;

		case 'd': /* request day */
			TM = localtime_r(&when, &s_TM);
			strftime(str, freespace, "%d", TM);
			break;

		case 'l': /* request timestamp */
			snprintf(str, freespace, "%lu",
				 (unsigned long) when);
			break;

		case 'm': /* request month */
			TM = localtime_r(&when, &s_TM);
			strftime(str, freespace, "%m", TM);
			break;

		case 't': /* request timestamp */
			CTIME_R(&when, str, freespace);
			nl = strchr(str, '\n');
			if (nl) *nl = '\0';
			break;

		case 'D': /* request date */
			TM = localtime_r(&when, &s_TM);
			strftime(str, freespace, "%Y%m%d", TM);
			break;

		case 'G': /* request minute */
			TM = localtime_r(&when, &s_TM);
			strftime(str, freespace, "%M", TM);
			break;

		case 'H': /* request hour */
			TM = localtime_r(&when, &s_TM);
			strftime(str, freespace, "%H", TM);
			break;

		case 'I': /* Request ID */
			if (request->packet) {
				snprintf(str, freespace, "%i", request->packet->id);
			}
			break;

		case 'S': /* request timestamp in SQL format*/
			TM = localtime_r(&when, &s_TM);
			strftime(str, freespace, "%Y-%m-%d %H:%M:%S", TM);
			break;

		case 'T': /* request timestamp */
			TM = localtime_r(&when, &s_TM);
			strftime(str, freespace, "%Y-%m-%d-%H.%M.%S.000000", TM);
			break;

		case 'Y': /* request year */
			TM = localtime_r(&when, &s_TM);
			strftime(str, freespace, "%Y", TM);
			break;

		default:
			rad_assert(0 == 1);
			break;
		}
	}
		break;

	case XLAT_ATTRIBUTE:
		ref = request;
		if (radius_request(&ref, node->ref) < 0) {
			return NULL;
		}

		/*
		 *	Some attributes are virtual <sigh>
		 */
		str = xlat_getvp(ctx, ref, node->list, node->da, node->tag, true);
		if (!str) {
			str = talloc_zero_array(ctx, char, 1);
		}
		XLAT_DEBUG("expand attr %s --> '%s'", node->da->name, str);
		break;

	case XLAT_VIRTUAL:
		str = talloc_array(ctx, char, 1024); /* FIXME: have the module call talloc_asprintf */
		rcode = node->xlat->func(node->xlat->instance, request, NULL, str, 1024);
		if (rcode < 0) {
			talloc_free(str);
			return NULL;
		}
		break;

	case XLAT_MODULE:
		rad_assert(node->child != NULL);
		if (xlat_process(&child, request, node->child, node->xlat->escape, node->xlat->instance) == 0) {
			return NULL;
		}

		XLAT_DEBUG("%.*sexpand mod %s --> '%s'", lvl, xlat_spaces, node->fmt, child);

		str = talloc_array(ctx, char, 1024); /* FIXME: have the module call talloc_asprintf */
		*str = '\0';	/* Be sure the string is NULL terminated, we now only free on error */
		
		rcode = node->xlat->func(node->xlat->instance, request, child, str, 1024);
		talloc_free(child);
		if (rcode < 0) {
			talloc_free(str);
			return NULL;
		}
		break;

#ifdef HAVE_REGEX_H
	case XLAT_REGEX:
		child = request_data_reference(request, request,
					       REQUEST_DATA_REGEX | node->num);
		if (!child) return NULL;

		str = talloc_strdup(ctx, child);
		break;
#endif

	case XLAT_ALTERNATE:
		rad_assert(node->child != NULL);
		rad_assert(node->alternate != NULL);

		/*
		 *	Special-case first situation being an
		 *	attribute.
		 */
		if (node->child->type == XLAT_ATTRIBUTE) {
			str = NULL;
			ref = request;

			if (radius_request(&ref, node->child->ref) >= 0) {
				str = xlat_getvp(ctx, ref, node->child->list, node->child->da, node->child->tag, true);
			}
		} else {
			str = xlat_aprint(ctx, request, node->child, escape, escape_ctx, lvl);
		}
		if (str) break;

		str = xlat_aprint(ctx, request, node->alternate, escape, escape_ctx, lvl);
		break;

	}
Esempio n. 9
0
static ssize_t xlat_tokenize_alternation(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
					 char const **error)
{
	ssize_t slen;
	char *p;
	xlat_exp_t *node;

	rad_assert(fmt[0] == '%');
	rad_assert(fmt[1] == '{');
	rad_assert(fmt[2] == '%');
	rad_assert(fmt[3] == '{');

	XLAT_DEBUG("ALTERNATE: %s", fmt);

	node = talloc_zero(ctx, xlat_exp_t);
	node->type = XLAT_ALTERNATE;

	p = fmt + 2;
	slen = xlat_tokenize_expansion(node, p, &node->child, error);
	if (slen <= 0) {
		talloc_free(node);
		return slen - (p - fmt);
	}
	p += slen;

	if (p[0] != ':') {
		talloc_free(node);
		*error = "Expected ':' after first expansion";
		return -(p - fmt);
	}
	p++;

	if (p[0] != '-') {
		talloc_free(node);
		*error = "Expected '-' after ':'";
		return -(p - fmt);
	}
	p++;

	/*
	 *	Allow the RHS to be empty as a special case.
	 */
	if (*p == '}') {
		/*
		 *	Hack up an empty string.
		 */
		node->alternate = talloc_zero(node, xlat_exp_t);
		node->alternate->type = XLAT_LITERAL;
		node->alternate->fmt = talloc_strdup(node->alternate, "");
		*(p++) = '\0';

	} else {
		slen = xlat_tokenize_literal(node, p,  &node->alternate, true, error);
		if (slen <= 0) {
			talloc_free(node);
			return slen - (p - fmt);
		}

		if (!node->alternate) {
			talloc_free(node);
			*error = "Empty expansion is invalid";
			return -(p - fmt);
		}
		p += slen;
	}

	*head = node;
	return p - fmt;
}
Esempio n. 10
0
static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, 
				  struct loadparm_context *lp_ctx,
				  char *buf, int length, void **private1,
				  unsigned int mux_id, void **private2) 
{
	DATA_BLOB in;
	DATA_BLOB out = data_blob(NULL, 0);
	char *out_base64 = NULL;
	const char *reply_arg = NULL;
	struct gensec_ntlm_state {
		struct gensec_security *gensec_state;
		const char *set_password;
	};
	struct gensec_ntlm_state *state;
	struct tevent_context *ev;
	struct messaging_context *msg;

	NTSTATUS nt_status;
	bool first = false;
	const char *reply_code;
	struct cli_credentials *creds;

	static char *want_feature_list = NULL;
	static DATA_BLOB session_key;

	TALLOC_CTX *mem_ctx;

	if (*private1) {
		state = (struct gensec_ntlm_state *)*private1;
	} else {
		state = talloc_zero(NULL, struct gensec_ntlm_state);
		if (!state) {
			mux_printf(mux_id, "BH No Memory\n");
			exit(1);
		}
		*private1 = state;
		if (opt_password) {
			state->set_password = opt_password;
		}
	}
	
	if (strlen(buf) < 2) {
		DEBUG(1, ("query [%s] invalid", buf));
		mux_printf(mux_id, "BH Query invalid\n");
		return;
	}

	if (strlen(buf) > 3) {
		if(strncmp(buf, "SF ", 3) == 0) {
			DEBUG(10, ("Setting flags to negotiate\n"));
			talloc_free(want_feature_list);
			want_feature_list = talloc_strndup(state, buf+3, strlen(buf)-3);
			mux_printf(mux_id, "OK\n");
			return;
		}
		in = base64_decode_data_blob(NULL, buf + 3);
	} else {
		in = data_blob(NULL, 0);
	}

	if (strncmp(buf, "YR", 2) == 0) {
		if (state->gensec_state) {
			talloc_free(state->gensec_state);
			state->gensec_state = NULL;
		}
	} else if ( (strncmp(buf, "OK", 2) == 0)) {
		/* Just return BH, like ntlm_auth from Samba 3 does. */
		mux_printf(mux_id, "BH Command expected\n");
		data_blob_free(&in);
		return;
	} else if ( (strncmp(buf, "TT ", 3) != 0) &&
		    (strncmp(buf, "KK ", 3) != 0) &&
		    (strncmp(buf, "AF ", 3) != 0) &&
		    (strncmp(buf, "NA ", 3) != 0) && 
		    (strncmp(buf, "UG", 2) != 0) && 
		    (strncmp(buf, "PW ", 3) != 0) &&
		    (strncmp(buf, "GK", 2) != 0) &&
		    (strncmp(buf, "GF", 2) != 0)) {
		DEBUG(1, ("SPNEGO request [%s] invalid\n", buf));
		mux_printf(mux_id, "BH SPNEGO request invalid\n");
		data_blob_free(&in);
		return;
	}

	ev = s4_event_context_init(state);
	if (!ev) {
		exit(1);
	}

	mem_ctx = talloc_named(NULL, 0, "manage_gensec_request internal mem_ctx");

	/* setup gensec */
	if (!(state->gensec_state)) {
		switch (stdio_helper_mode) {
		case GSS_SPNEGO_CLIENT:
		case NTLMSSP_CLIENT_1:
			/* setup the client side */

			nt_status = gensec_client_start(NULL, &state->gensec_state, ev, 
							lpcfg_gensec_settings(NULL, lp_ctx));
			if (!NT_STATUS_IS_OK(nt_status)) {
				talloc_free(mem_ctx);
				exit(1);
			}

			break;
		case GSS_SPNEGO_SERVER:
		case SQUID_2_5_NTLMSSP:
		{
			const char *winbind_method[] = { "winbind", NULL };
			struct auth_context *auth_context;

			msg = messaging_client_init(state, lpcfg_messaging_path(state, lp_ctx), ev);
			if (!msg) {
				talloc_free(mem_ctx);
				exit(1);
			}
			nt_status = auth_context_create_methods(mem_ctx, 
								winbind_method,
								ev, 
								msg, 
								lp_ctx,
								NULL,
								&auth_context);
	
			if (!NT_STATUS_IS_OK(nt_status)) {
				talloc_free(mem_ctx);
				exit(1);
			}
			
			if (!NT_STATUS_IS_OK(gensec_server_start(state, ev, 
								 lpcfg_gensec_settings(state, lp_ctx),
								 auth_context, &state->gensec_state))) {
				talloc_free(mem_ctx);
				exit(1);
			}
			break;
		}
		default:
			talloc_free(mem_ctx);
			abort();
		}

		creds = cli_credentials_init(state->gensec_state);
		cli_credentials_set_conf(creds, lp_ctx);
		if (opt_username) {
			cli_credentials_set_username(creds, opt_username, CRED_SPECIFIED);
		}
		if (opt_domain) {
			cli_credentials_set_domain(creds, opt_domain, CRED_SPECIFIED);
		}
		if (state->set_password) {
			cli_credentials_set_password(creds, state->set_password, CRED_SPECIFIED);
		} else {
			cli_credentials_set_password_callback(creds, get_password);
			creds->priv_data = (void*)(uintptr_t)mux_id;
		}
		if (opt_workstation) {
			cli_credentials_set_workstation(creds, opt_workstation, CRED_SPECIFIED);
		}
		
		switch (stdio_helper_mode) {
		case GSS_SPNEGO_SERVER:
		case SQUID_2_5_NTLMSSP:
			cli_credentials_set_machine_account(creds, lp_ctx);
			break;
		default:
			break;
		}

		gensec_set_credentials(state->gensec_state, creds);
		gensec_want_feature_list(state->gensec_state, want_feature_list);

		switch (stdio_helper_mode) {
		case GSS_SPNEGO_CLIENT:
		case GSS_SPNEGO_SERVER:
			nt_status = gensec_start_mech_by_oid(state->gensec_state, GENSEC_OID_SPNEGO);
			if (!in.length) {
				first = true;
			}
			break;
		case NTLMSSP_CLIENT_1:
			if (!in.length) {
				first = true;
			}
			/* fall through */
		case SQUID_2_5_NTLMSSP:
			nt_status = gensec_start_mech_by_oid(state->gensec_state, GENSEC_OID_NTLMSSP);
			break;
		default:
			talloc_free(mem_ctx);
			abort();
		}

		if (!NT_STATUS_IS_OK(nt_status)) {
			DEBUG(1, ("GENSEC mech failed to start: %s\n", nt_errstr(nt_status)));
			mux_printf(mux_id, "BH GENSEC mech failed to start\n");
			talloc_free(mem_ctx);
			return;
		}

	}

	/* update */

	if (strncmp(buf, "PW ", 3) == 0) {
		state->set_password = talloc_strndup(state,
						     (const char *)in.data, 
						     in.length);
		
		cli_credentials_set_password(gensec_get_credentials(state->gensec_state),
					     state->set_password,
					     CRED_SPECIFIED);
		mux_printf(mux_id, "OK\n");
		data_blob_free(&in);
		talloc_free(mem_ctx);
		return;
	}

	if (strncmp(buf, "UG", 2) == 0) {
		int i;
		char *grouplist = NULL;
		struct auth_session_info *session_info;

		nt_status = gensec_session_info(state->gensec_state, &session_info); 
		if (!NT_STATUS_IS_OK(nt_status)) {
			DEBUG(1, ("gensec_session_info failed: %s\n", nt_errstr(nt_status)));
			mux_printf(mux_id, "BH %s\n", nt_errstr(nt_status));
			data_blob_free(&in);
			talloc_free(mem_ctx);
			return;
		}
		
		/* get the string onto the context */
		grouplist = talloc_strdup(mem_ctx, "");
		
		for (i=0; i<session_info->security_token->num_sids; i++) {
			struct security_token *token = session_info->security_token; 
			const char *sidstr = dom_sid_string(session_info, 
							    &token->sids[i]);
			grouplist = talloc_asprintf_append_buffer(grouplist, "%s,", sidstr);
		}

		mux_printf(mux_id, "GL %s\n", grouplist);
		talloc_free(session_info);
		data_blob_free(&in);
		talloc_free(mem_ctx);
		return;
	}

	if (strncmp(buf, "GK", 2) == 0) {
		char *base64_key;
		DEBUG(10, ("Requested session key\n"));
		nt_status = gensec_session_key(state->gensec_state, &session_key);
		if(!NT_STATUS_IS_OK(nt_status)) {
			DEBUG(1, ("gensec_session_key failed: %s\n", nt_errstr(nt_status)));
			mux_printf(mux_id, "BH No session key\n");
			talloc_free(mem_ctx);
			return;
		} else {
			base64_key = base64_encode_data_blob(state, session_key);
			mux_printf(mux_id, "GK %s\n", base64_key);
			talloc_free(base64_key);
		}
		talloc_free(mem_ctx);
		return;
	}

	if (strncmp(buf, "GF", 2) == 0) {
		struct ntlmssp_state *ntlmssp_state;
		uint32_t neg_flags;

		ntlmssp_state = talloc_get_type(state->gensec_state->private_data,
				struct ntlmssp_state);
		neg_flags = ntlmssp_state->neg_flags;

		DEBUG(10, ("Requested negotiated feature flags\n"));
		mux_printf(mux_id, "GF 0x%08x\n", neg_flags);
		return;
	}

	nt_status = gensec_update(state->gensec_state, mem_ctx, in, &out);
	
	/* don't leak 'bad password'/'no such user' info to the network client */
	nt_status = nt_status_squash(nt_status);

	if (out.length) {
		out_base64 = base64_encode_data_blob(mem_ctx, out);
	} else {
		out_base64 = NULL;
	}

	if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
		reply_arg = "*";
		if (first) {
			reply_code = "YR";
		} else if (state->gensec_state->gensec_role == GENSEC_CLIENT) { 
			reply_code = "KK";
		} else if (state->gensec_state->gensec_role == GENSEC_SERVER) { 
			reply_code = "TT";
		} else {
			abort();
		}


	} else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED)) {
		reply_code = "BH NT_STATUS_ACCESS_DENIED";
		reply_arg = nt_errstr(nt_status);
		DEBUG(1, ("GENSEC login failed: %s\n", nt_errstr(nt_status)));
	} else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_UNSUCCESSFUL)) {
		reply_code = "BH NT_STATUS_UNSUCCESSFUL";
		reply_arg = nt_errstr(nt_status);
		DEBUG(1, ("GENSEC login failed: %s\n", nt_errstr(nt_status)));
	} else if (!NT_STATUS_IS_OK(nt_status)) {
		reply_code = "NA";
		reply_arg = nt_errstr(nt_status);
		DEBUG(1, ("GENSEC login failed: %s\n", nt_errstr(nt_status)));
	} else if /* OK */ (state->gensec_state->gensec_role == GENSEC_SERVER) {
		struct auth_session_info *session_info;

		nt_status = gensec_session_info(state->gensec_state, &session_info);
		if (!NT_STATUS_IS_OK(nt_status)) {
			reply_code = "BH Failed to retrive session info";
			reply_arg = nt_errstr(nt_status);
			DEBUG(1, ("GENSEC failed to retrieve the session info: %s\n", nt_errstr(nt_status)));
		} else {

			reply_code = "AF";
			reply_arg = talloc_asprintf(state->gensec_state, 
						    "%s%s%s", session_info->info->domain_name,
						    lpcfg_winbind_separator(lp_ctx), session_info->info->account_name);
			talloc_free(session_info);
		}
	} else if (state->gensec_state->gensec_role == GENSEC_CLIENT) {
		reply_code = "AF";
		reply_arg = out_base64;
	} else {
		abort();
	}

	switch (stdio_helper_mode) {
	case GSS_SPNEGO_SERVER:
		mux_printf(mux_id, "%s %s %s\n", reply_code, 
			  out_base64 ? out_base64 : "*", 
			  reply_arg ? reply_arg : "*");
		break;
	default:
		if (out_base64) {
			mux_printf(mux_id, "%s %s\n", reply_code, out_base64);
		} else if (reply_arg) {
			mux_printf(mux_id, "%s %s\n", reply_code, reply_arg);
		} else {
			mux_printf(mux_id, "%s\n", reply_code);
		}
	}

	talloc_free(mem_ctx);
	return;
}
Esempio n. 11
0
static void manage_squid_request(struct loadparm_context *lp_ctx, enum stdio_helper_mode helper_mode,
				 stdio_helper_function fn, void **private2) 
{
	char *buf;
	char tmp[INITIAL_BUFFER_SIZE+1];
	unsigned int mux_id = 0;
	int length, buf_size = 0;
	char *c;
	struct mux_private {
		unsigned int max_mux;
		void **private_pointers;
	};

	static struct mux_private *mux_private;
	static void *normal_private;
	void **private1;

	buf = talloc_strdup(NULL, "");

	if (buf == NULL) {
		DEBUG(0, ("Failed to allocate memory for reading the input "
			  "buffer.\n"));
		x_fprintf(x_stdout, "ERR\n");
		return;
	}

	do {
		/* this is not a typo - x_fgets doesn't work too well under
		 * squid */
		if (fgets(tmp, INITIAL_BUFFER_SIZE, stdin) == NULL) {
			if (ferror(stdin)) {
				DEBUG(1, ("fgets() failed! dying..... errno=%d "
					  "(%s)\n", ferror(stdin),
					  strerror(ferror(stdin))));

				exit(1);    /* BIIG buffer */
			}
			exit(0);
		}

		buf = talloc_strdup_append_buffer(buf, tmp);
		buf_size += INITIAL_BUFFER_SIZE;

		if (buf_size > MAX_BUFFER_SIZE) {
			DEBUG(0, ("Invalid Request (too large)\n"));
			x_fprintf(x_stdout, "ERR\n");
			talloc_free(buf);
			return;
		}

		c = strchr(buf, '\n');
	} while (c == NULL);

	*c = '\0';
	length = c-buf;

	DEBUG(10, ("Got '%s' from squid (length: %d).\n",buf,length));

	if (buf[0] == '\0') {
		DEBUG(0, ("Invalid Request (empty)\n"));
		x_fprintf(x_stdout, "ERR\n");
		talloc_free(buf);
		return;
	}

	if (opt_multiplex) {
		if (sscanf(buf, "%u ", &mux_id) != 1) {
			DEBUG(0, ("Invalid Request - no multiplex id\n"));
			x_fprintf(x_stdout, "ERR\n");
			talloc_free(buf);
			return;
		}
		if (!mux_private) {
			mux_private = talloc(NULL, struct mux_private);
			mux_private->max_mux = 0;
			mux_private->private_pointers = NULL;
		}
		
		c=strchr(buf,' ');
		if (!c) {
			DEBUG(0, ("Invalid Request - no data after multiplex id\n"));
			x_fprintf(x_stdout, "ERR\n");
			talloc_free(buf);
			return;
		}
		c++;
		if (mux_id >= mux_private->max_mux) {
			unsigned int prev_max = mux_private->max_mux;
			mux_private->max_mux = mux_id + 1;
			mux_private->private_pointers
				= talloc_realloc(mux_private, 
						   mux_private->private_pointers, 
						   void *, mux_private->max_mux);
			memset(&mux_private->private_pointers[prev_max], '\0',  
			       (sizeof(*mux_private->private_pointers) * (mux_private->max_mux - prev_max))); 
		};
Esempio n. 12
0
static NTSTATUS local_pw_check_specified(struct loadparm_context *lp_ctx,
					 const char *username, 
					 const char *domain, 
					 const char *workstation,
					 const DATA_BLOB *challenge, 
					 const DATA_BLOB *lm_response, 
					 const DATA_BLOB *nt_response, 
					 uint32_t flags, 
					 DATA_BLOB *lm_session_key, 
					 DATA_BLOB *user_session_key, 
					 char **error_string, 
					 char **unix_name) 
{
	NTSTATUS nt_status;
	struct samr_Password lm_pw, nt_pw;
	struct samr_Password *lm_pwd, *nt_pwd;
	TALLOC_CTX *mem_ctx = talloc_init("local_pw_check_specified");
	if (!mem_ctx) {
		nt_status = NT_STATUS_NO_MEMORY;
	} else {
		
		E_md4hash(opt_password, nt_pw.hash);
		if (E_deshash(opt_password, lm_pw.hash)) {
			lm_pwd = &lm_pw;
		} else {
			lm_pwd = NULL;
		}
		nt_pwd = &nt_pw;
		
		
		nt_status = ntlm_password_check(mem_ctx, 
						lpcfg_lanman_auth(lp_ctx),
						lpcfg_ntlm_auth(lp_ctx),
						MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
						MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT,
						challenge,
						lm_response,
						nt_response,
						username,
						username,
						domain,
						lm_pwd, nt_pwd, user_session_key, lm_session_key);
		
		if (NT_STATUS_IS_OK(nt_status)) {
			if (unix_name) {
				if (asprintf(unix_name, "%s%c%s", domain,
					     *lpcfg_winbind_separator(lp_ctx),
					     username) < 0) {
					nt_status = NT_STATUS_NO_MEMORY;
				}
			}
		} else {
			DEBUG(3, ("Login for user [%s]\\[%s]@[%s] failed due to [%s]\n", 
				  domain, username, workstation, 
				  nt_errstr(nt_status)));
		}
		talloc_free(mem_ctx);
	}
	if (error_string) {
		*error_string = strdup(nt_errstr(nt_status));
	}
	return nt_status;
	
	
}
Esempio n. 13
0
/*
 * given a radius request with many attributes in the EAP-SIM range, build
 * them all into a single EAP-SIM body.
 *
 */
int map_eapsim_basictypes(RADIUS_PACKET *r, eap_packet_t *ep)
{
	VALUE_PAIR	*vp;
	int		encoded_size;
	uint8_t		*encodedmsg, *attr;
	unsigned int	id, eapcode;
	uint8_t		*macspace;
	uint8_t const	*append;
	int		appendlen;
	unsigned char	subtype;
	vp_cursor_t	cursor;

	macspace = NULL;
	append = NULL;
	appendlen = 0;

	/*
	 * encodedmsg is now an EAP-SIM message.
	 * it might be too big for putting into an EAP-Type-SIM
	 *
	 */
	subtype = (vp = fr_pair_find_by_num(r->vps, 0, PW_EAP_SIM_SUBTYPE, TAG_ANY)) ?
		vp->vp_integer : EAPSIM_START;

	id = (vp = fr_pair_find_by_num(r->vps, 0, PW_EAP_ID, TAG_ANY)) ?
		vp->vp_integer : ((int)getpid() & 0xff);

	eapcode = (vp = fr_pair_find_by_num(r->vps, 0, PW_EAP_CODE, TAG_ANY)) ?
		vp->vp_integer : PW_EAP_REQUEST;

	/*
	 * take a walk through the attribute list to see how much space
	 * that we need to encode all of this.
	 */
	encoded_size = 0;
	for (vp = fr_cursor_init(&cursor, &r->vps);
	     vp;
	     vp = fr_cursor_next(&cursor)) {
		int roundedlen;
		int vplen;

		if ((vp->da->attr < PW_EAP_SIM_BASE) || (vp->da->attr >= (PW_EAP_SIM_BASE + 256))) {
			continue;
		}

		vplen = vp->vp_length;

		/*
		 * the AT_MAC attribute is a bit different, when we get to this
		 * attribute, we pull the contents out, save it for later
		 * processing, set the size to 16 bytes (plus 2 bytes padding).
		 *
		 * At this point, we only care about the size.
		 */
		if(vp->da->attr == PW_EAP_SIM_MAC) {
			vplen = 18;
		}

		/* round up to next multiple of 4, after taking in
		 * account the type and length bytes
		 */
		roundedlen = (vplen + 2 + 3) & ~3;
		encoded_size += roundedlen;
	}

	if (ep->code != PW_EAP_SUCCESS) {
		ep->code = eapcode;
	}

	ep->id = (id & 0xff);
	ep->type.num = PW_EAP_SIM;

	/*
	 * if no attributes were found, do very little.
	 *
	 */
	if (encoded_size == 0) {
		encodedmsg = talloc_array(ep, uint8_t, 3);
		/* FIX: could be NULL */

		encodedmsg[0] = subtype;
		encodedmsg[1] = 0;
		encodedmsg[2] = 0;

		ep->type.length = 3;
		ep->type.data = encodedmsg;

		return 0;
	}


	/*
	 * figured out the length, so allocate some space for the results.
	 *
	 * Note that we do not bother going through an "EAP" stage, which
	 * is a bit strange compared to the unmap, which expects to see
	 * an EAP-SIM virtual attributes.
	 *
	 * EAP is 1-code, 1-identifier, 2-length, 1-type = 5 overhead.
	 *
	 * SIM code adds a subtype, and 2 bytes of reserved = 3.
	 *
	 */
	encoded_size += 3;
	encodedmsg = talloc_array(ep, uint8_t, encoded_size);
	if (!encodedmsg) {
		return 0;
	}
	memset(encodedmsg, 0, encoded_size);

	/*
	 * now walk the attributes again, sticking them in.
	 *
	 * we go three bytes into the encoded message, because there are two
	 * bytes of reserved, and we will fill the "subtype" in later.
	 *
	 */
	attr = encodedmsg+3;

	for (vp = fr_cursor_first(&cursor); vp; vp = fr_cursor_next(&cursor)) {
		int roundedlen;

		if(vp->da->attr < PW_EAP_SIM_BASE ||
		   vp->da->attr >= PW_EAP_SIM_BASE + 256) {
			continue;
		}

		/*
		 * the AT_MAC attribute is a bit different, when we get to this
		 * attribute, we pull the contents out, save it for later
		 * processing, set the size to 16 bytes (plus 2 bytes padding).
		 *
		 * At this point, we put in zeros, and remember where the
		 * sixteen bytes go.
		 */
		if(vp->da->attr == PW_EAP_SIM_MAC) {
			roundedlen = 20;
			memset(&attr[2], 0, 18);
			macspace = &attr[4];
			append = vp->vp_octets;
			appendlen = vp->vp_length;
		} else {
			roundedlen = (vp->vp_length + 2 + 3) & ~3;
			memset(attr, 0, roundedlen);
			memcpy(&attr[2], vp->vp_strvalue, vp->vp_length);
		}
		attr[0] = vp->da->attr - PW_EAP_SIM_BASE;
		attr[1] = roundedlen >> 2;

		attr += roundedlen;
	}

	encodedmsg[0] = subtype;

	ep->type.length = encoded_size;
	ep->type.data = encodedmsg;

	/*
	 * if macspace was set and we have a key,
	 * then we should calculate the HMAC-SHA1 of the resulting EAP-SIM
	 * packet, appended with the value of append.
	 */
	vp = fr_pair_find_by_num(r->vps, 0, PW_EAP_SIM_KEY, TAG_ANY);
	if(macspace != NULL && vp != NULL) {
		unsigned char		*buffer;
		eap_packet_raw_t	*hdr;
		uint16_t		hmaclen, total_length = 0;
		unsigned char		sha1digest[20];

		total_length = EAP_HEADER_LEN + 1 + encoded_size;
		hmaclen = total_length + appendlen;
		buffer = talloc_array(r, uint8_t, hmaclen);
		hdr = (eap_packet_raw_t *) buffer;
		if (!hdr) {
			talloc_free(encodedmsg);
			return 0;
		}

		hdr->code = eapcode & 0xFF;
		hdr->id = (id & 0xFF);
		total_length = htons(total_length);
		memcpy(hdr->length, &total_length, sizeof(total_length));

		hdr->data[0] = PW_EAP_SIM;

		/* copy the data */
		memcpy(&hdr->data[1], encodedmsg, encoded_size);

		/* copy the nonce */
		memcpy(&hdr->data[encoded_size+1], append, appendlen);

		/* HMAC it! */
		fr_hmac_sha1(sha1digest, buffer, hmaclen, vp->vp_octets, vp->vp_length);

		/* done with the buffer, free it */
		talloc_free(buffer);

		/* now copy the digest to where it belongs in the AT_MAC */
		/* note that it is truncated to 128-bits */
		memcpy(macspace, sha1digest, 16);
	}

	/* if we had an AT_MAC and no key, then fail */
	if ((macspace != NULL) && !vp) {
		if (encodedmsg != NULL) {
			talloc_free(encodedmsg);
		}

		return 0;
	}

	return 1;
}
Esempio n. 14
0
/*
 * calculate the MAC for the EAP message, given the key.
 * The "extra" will be appended to the EAP message and included in the
 * HMAC.
 *
 */
int eapsim_checkmac(TALLOC_CTX *ctx, VALUE_PAIR *rvps, uint8_t key[EAPSIM_AUTH_SIZE], uint8_t *extra, int extralen,
		    uint8_t calcmac[20])
{
	int ret;
	eap_packet_raw_t *e;
	uint8_t *buffer;
	int elen,len;
	VALUE_PAIR *mac;

	mac = fr_pair_find_by_num(rvps, 0, PW_EAP_SIM_MAC, TAG_ANY);

	if(!mac || mac->vp_length != 18) {
		/* can't check a packet with no AT_MAC attribute */
		return 0;
	}

	/* get original copy of EAP message, note that it was sanitized
	 * to have a valid length, which we depend upon.
	 */
	e = eap_vp2packet(ctx, rvps);
	if (!e) return 0;

	/* make copy big enough for everything */
	elen = (e->length[0] * 256) + e->length[1];
	len = elen + extralen;

	buffer = talloc_array(ctx, uint8_t, len);
	if (!buffer) {
		talloc_free(e);
		return 0;
	}

	memcpy(buffer, e, elen);
	memcpy(buffer + elen, extra, extralen);

	/*
	 * now look for the AT_MAC attribute in the copy of the buffer
	 * and make sure that the checksum is zero.
	 *
	 */
	{
		uint8_t *attr;

		/* first attribute is 8 bytes into the EAP packet.
		 * 4 bytes for EAP, 1 for type, 1 for subtype, 2 reserved.
		 */
		attr = buffer+8;
		while(attr < (buffer+elen)) {
			if (attr[0] == (PW_EAP_SIM_MAC - PW_EAP_SIM_BASE)) {
				/* zero the data portion, after making sure
				 * the size is >=5. Maybe future versions.
				 * will use more bytes, so be liberal.
				 */
				if(attr[1] < 5) {
					ret = 0;
					goto done;
				}
				memset(&attr[4], 0, (attr[1]-1)*4);
			}
			/* advance the pointer */
			attr += attr[1]*4;
		}
	}

	/* now, HMAC-SHA1 it with the key. */
	fr_hmac_sha1(calcmac, buffer, len, key, 16);

	ret = memcmp(&mac->vp_strvalue[2], calcmac, 16) == 0 ? 1 : 0;
 done:
	talloc_free(e);
	talloc_free(buffer);
	return(ret);
}
Esempio n. 15
0
int m_config_parse(m_config_t *config, const char *location, bstr data,
                   char *initial_section, int flags)
{
    m_profile_t *profile = m_config_add_profile(config, initial_section);
    void *tmp = talloc_new(NULL);
    int line_no = 0;
    int errors = 0;

    bstr_eatstart0(&data, "\xEF\xBB\xBF"); // skip BOM

    while (data.len) {
        talloc_free_children(tmp);
        bool ok = false;

        line_no++;
        char loc[512];
        snprintf(loc, sizeof(loc), "%s:%d:", location, line_no);

        bstr line = bstr_strip_linebreaks(bstr_getline(data, &data));
        if (!skip_ws(&line))
            continue;

        // Profile declaration
        if (bstr_eatstart0(&line, "[")) {
            bstr profilename;
            if (!bstr_split_tok(line, "]", &profilename, &line)) {
                MP_ERR(config, "%s missing closing ]\n", loc);
                goto error;
            }
            if (skip_ws(&line)) {
                MP_ERR(config, "%s unparseable extra characters: '%.*s'\n",
                       loc, BSTR_P(line));
                goto error;
            }
            profile = m_config_add_profile(config, bstrto0(tmp, profilename));
            continue;
        }

        bstr_eatstart0(&line, "--");

        bstr option = line;
        while (line.len && (mp_isalnum(line.start[0]) || line.start[0] == '_' ||
                            line.start[0] == '-'))
            line = bstr_cut(line, 1);
        option.len = option.len - line.len;
        skip_ws(&line);

        bstr value = {0};
        if (bstr_eatstart0(&line, "=")) {
            skip_ws(&line);
            if (line.len && (line.start[0] == '"' || line.start[0] == '\'')) {
                // Simple quoting, like "value"
                char term[2] = {line.start[0], 0};
                line = bstr_cut(line, 1);
                if (!bstr_split_tok(line, term, &value, &line)) {
                    MP_ERR(config, "%s unterminated quote\n", loc);
                    goto error;
                }
            } else if (bstr_eatstart0(&line, "%")) {
                // Quoting with length, like %5%value
                bstr rest;
                long long len = bstrtoll(line, &rest, 10);
                if (rest.len == line.len || !bstr_eatstart0(&rest, "%") ||
                    len > rest.len)
                {
                    MP_ERR(config, "%s fixed-length quoting expected - put "
                           "\"quotes\" around the option value if you did not "
                           "intend to use this, but your option value starts "
                           "with '%%'\n", loc);
                    goto error;
                }
                value = bstr_splice(rest, 0, len);
                line = bstr_cut(rest, len);
            } else {
                // No quoting; take everything until the comment or end of line
                int end = bstrchr(line, '#');
                value = bstr_strip(end < 0 ? line : bstr_splice(line, 0, end));
                line.len = 0;
            }
        }
        if (skip_ws(&line)) {
            MP_ERR(config, "%s unparseable extra characters: '%.*s'\n",
                   loc, BSTR_P(line));
            goto error;
        }

        int res;
        if (bstr_equals0(option, "profile-desc")) {
            m_profile_set_desc(profile, value);
            res = 0;
        } else {
            res = m_config_set_profile_option(config, profile, option, value);
        }
        if (res < 0) {
            MP_ERR(config, "%s setting option %.*s='%.*s' failed.\n",
                   loc, BSTR_P(option), BSTR_P(value));
            goto error;
        }

        ok = true;
    error:
        if (!ok)
            errors++;
        if (errors > 16) {
            MP_ERR(config, "%s: too many errors, stopping.\n", location);
            break;
        }
    }

    if (config->recursion_depth == 0)
        m_config_finish_default_profile(config, flags);

    talloc_free(tmp);
    return 1;
}
Esempio n. 16
0
static ssize_t xlat_tokenize_expansion(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
				       char const **error)
{
	ssize_t slen;
	char *p, *q, *brace;
	char const *attrname;
	xlat_exp_t *node;

	rad_assert(fmt[0] == '%');
	rad_assert(fmt[1] == '{');

	/*
	 *	%{%{...}:-bar}
	 */
	if ((fmt[2] == '%') && (fmt[3] == '{')) {
		return xlat_tokenize_alternation(ctx, fmt, head, error);
	}

	XLAT_DEBUG("EXPANSION: %s", fmt);
	node = talloc_zero(ctx, xlat_exp_t);
	attrname = node->fmt = fmt + 2;
	node->len = 0;

#ifdef HAVE_REGEX_H
	/*
	 *	Handle regex's specially.
	 */
	if (isdigit((int) fmt[2]) && (fmt[3] == '}')) {
		if (fmt[2] == '9') {
			talloc_free(node);
			*error = "Invalid regex reference";
			return -2;
		}

		XLAT_DEBUG("REGEX: %s", fmt);
		fmt[3] = '\0';
		node->num = fmt[2] - '0'; /* ASCII */

		node->type = XLAT_REGEX;
		*head = node;
		return 4;
	}
#endif /* HAVE_REGEX_H */

	/*
	 *	%{Attr-Name}
	 *	%{Attr-Name[#]}
	 *	%{Tunnel-Password:1}
	 *	%{Tunnel-Password:1[#]}
	 *	%{request:Attr-Name}
	 *	%{request:Tunnel-Password:1}
	 *	%{request:Tunnel-Password:1[#]}
	 *	%{mod:foo}
	 */
	q = brace = NULL;
	for (p = fmt + 2; *p != '\0'; p++) {
		if (*p == ':') break;

		if (isspace((int) *p)) break;

		if (*p == '[') break;

		if (*p == '}') break;
	}

	if (*p != ':') p = NULL;

	/*
	 *	Might be a module name reference.
	 */
	if (p) {
		*p = '\0';

		/*
		 *	%{mod:foo}
		 */
		node->xlat = xlat_find(node->fmt);
		if (node->xlat) {
			node->type = XLAT_MODULE;
			
			XLAT_DEBUG("MOD: %s --> %s", node->fmt, p);
			slen = xlat_tokenize_literal(node, p + 1, &node->child, true, error);
			if (slen <= 0) {
				talloc_free(node);
				return slen - (p - fmt);
			}
			p += slen + 1;
			
			*head = node;
			rad_assert(node->next == NULL);
			return p - fmt;
		}

		/*
		 *	Modules can have '}' in their RHS, so we
		 *	didn't check for that until now.
		 *
		 *	As of now, node->fmt MUST be a reference to an
		 *	attribute, however complicated.  So it MUST have a closing brace.
		 */
		brace = strchr(p + 1, '}');
		if (!brace) goto no_brace;
		*brace = '\0';

		/*
		 *	%{User-Name}
		 *	%{User-Name[1]}
		 *	%{Tunnel-Password:1}
		 *	%{request:Tunnel-Password:1}
		 *
		 *	<sigh>  The syntax is fairly poor.
		 */
		XLAT_DEBUG("Looking for list in '%s'", attrname);

		/*
		 *	Not a module.  Has to be an attribute
		 *	reference.
		 *
		 *	As of v3, we've removed %{request: ..>} as
		 *	internally registered xlats.
		 */
		*p = ':';
		node->ref = radius_request_name(&attrname, REQUEST_CURRENT);
		rad_assert(node->ref != REQUEST_UNKNOWN);

		node->list = radius_list_name(&attrname, PAIR_LIST_REQUEST);
		if (node->list == PAIR_LIST_UNKNOWN) {
			talloc_free(node);
			*error = "Unknown module";
			return -2;
		}

		/*
		 *	Check for a trailing tag.
		 */
		p = strchr(attrname, ':');
		if (p) *p = '\0';
		
	} else {
		brace = strchr(attrname, '}');
		if (!brace) {
		no_brace:
			talloc_free(node);
			*error = "No matching closing brace";
			return -1;	/* second character of format string */
		}
		*brace = '\0';

		node->ref = REQUEST_CURRENT;
		node->list = PAIR_LIST_REQUEST;	
	}

	*brace = '\0';

	XLAT_DEBUG("Looking for attribute name in %s", attrname);

	/*
	 *	Allow for an array reference.  They come AFTER the
	 *	tag, if the tag exists.  Otherwise, they come after
	 *	the attribute name.
	 */
	if (p) {
		q = strchr(p + 1, '[');
	} else {
		q = strchr(attrname, '[');
	}
	if (q) *(q++) = '\0';

	if (!*attrname) {
		talloc_free(node);
		*error = "Empty expression is invalid";
		return -(attrname - fmt);
	}

	/*
	 *	It's either an attribute name, or a Tunnel-Password:TAG
	 *	with the ':' already set to NULL.
	 */
	node->da = dict_attrbyname(attrname);
	if (!node->da) {
		/*
		 *	Foreach.  Maybe other stuff, too.
		 */
		node->xlat = xlat_find(attrname);
		if (node->xlat) {
			node->type = XLAT_VIRTUAL;
			node->fmt = attrname;

			XLAT_DEBUG("VIRTUAL: %s --> %s", node->fmt);
			*head = node;
			rad_assert(node->next == NULL);
			brace++;
			return brace - fmt;
		}

		talloc_free(node);
		*error = "Unknown attribute";
		return -(attrname - fmt);
	}
	
	/*
	 *	Parse the tag.
	 */
	if (p) {
		unsigned long tag;
		char *end;

		if (!node->da->flags.has_tag) {
			talloc_free(node);
			*error = "Attribute cannot have a tag";
			return - (p - fmt);
		}

		tag = strtoul(p + 1, &end, 10);
		p++;
		
		if (tag == ULONG_MAX) {
			talloc_free(node);
			*error = "Invalid tag value";
			return - (p - fmt);
		}

		node->tag = tag;
		p = end;

		if (*p) {
			talloc_free(node);
			*error = "Unexpected text after tag";
			return - (p - fmt);
		}

	} else {
		node->tag = TAG_ANY;
		/* leave p alone */
	}

	/*
	 *	Check for array reference
	 */
	if (q) {
		unsigned long num;
		char *end;

		p = q;
		if (*p== '#') {
			node->num = 65536;
			p++;

		} else if (*p == '*') {
			node->num = 65537;
			p++;

		} else if (isdigit((int) *p)) {
			num = strtoul(p, &end, 10);
			if ((num == ULONG_MAX) || (num > 65535)) {
				talloc_free(node);
				*error = "Invalid number";
				return - (p - fmt);
			}
			p = end;
			DEBUG("END %s", p);
			node->num = num;

		} else {
			talloc_free(node);
			*error = "Invalid array reference";
			return - (p - fmt);
		}

		if (*p != ']') {
			talloc_free(node);
			*error = "Expected ']'";
			return - (p - fmt);
		}

		p++;
		if (*p) {
			talloc_free(node);
			*error = "Unexpected text after array reference";
			return - (p - fmt);
		}
	}

	rad_assert(!p || (p == brace));

	node->type = XLAT_ATTRIBUTE;
	p = brace + 1;

	*head = node;
	rad_assert(node->next == NULL);
	return p - fmt;
}
Esempio n. 17
0
static NTSTATUS sldb_create(struct share_context *ctx, const char *name, struct share_info *info, int count)
{
	struct ldb_context *ldb;
	struct ldb_message *msg;
	TALLOC_CTX *tmp_ctx;
	NTSTATUS ret;
	int err, i, j;

	for (i = 0, j = 0; i < count && j != 0x03; i++) {
		if (strcasecmp(info[i].name, SHARE_TYPE) == 0) j |= 0x02;
		if (strcasecmp(info[i].name, SHARE_PATH) == 0) j |= 0x01;
		if (strcasecmp(info[i].name, SHARE_NAME) == 0) {
			if (strcasecmp(name, (char *)info[i].value) != 0) {
				return NT_STATUS_INVALID_PARAMETER;
			}
		}
	}
	if (!name || j != 0x03) {
		return NT_STATUS_INVALID_PARAMETER;
	}
	
	tmp_ctx = talloc_new(NULL);
	if (!tmp_ctx) {
		DEBUG(0,("ERROR: Out of memory!\n"));
		return NT_STATUS_NO_MEMORY;
	}

	ldb = talloc_get_type(ctx->priv_data, struct ldb_context);

	msg = ldb_msg_new(tmp_ctx);
	if (!msg) {
		DEBUG(0,("ERROR: Out of memory!\n"));
		ret = NT_STATUS_NO_MEMORY;
		goto done;
	}

	/* TODO: escape info->name */
	msg->dn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s,CN=SHARES", name);
	if (!msg->dn) {
		DEBUG(0,("ERROR: Out of memory!\n"));
		ret = NT_STATUS_NO_MEMORY;
		goto done;
	}

	SHARE_ADD_STRING("objectClass", "top");
	SHARE_ADD_STRING("objectClass", "share");
	SHARE_ADD_STRING("cn", name);
	SHARE_ADD_STRING(SHARE_NAME, name);

	for (i = 0; i < count; i++) {
		if (strcasecmp(info[i].name, SHARE_NAME) == 0) continue;

		switch (info[i].type) {
		case SHARE_INFO_STRING:
			SHARE_ADD_STRING(info[i].name, (char *)info[i].value);
			break;
		case SHARE_INFO_INT:
			SHARE_ADD_INT(info[i].name, *((int *)info[i].value));
			break;
		case SHARE_INFO_BLOB:
			SHARE_ADD_BLOB(info[i].name, (DATA_BLOB *)info[i].value);
			break;
		default:
			DEBUG(2,("ERROR: Invalid share info type for %s\n", info[i].name));
			ret = NT_STATUS_INVALID_PARAMETER;
			goto done;
		}
	}

	/* TODO: Security Descriptor */

	SHARE_ADD_STRING(SHARE_AVAILABLE, "true");
	SHARE_ADD_STRING(SHARE_BROWSEABLE, "true");
	SHARE_ADD_STRING(SHARE_READONLY, "false");
	SHARE_ADD_STRING(SHARE_NTVFS_HANDLER, "unixuid");
	SHARE_ADD_STRING(SHARE_NTVFS_HANDLER, "posix");

	err = ldb_add(ldb, msg);
	if (err != LDB_SUCCESS) {
		DEBUG(2,("ERROR: unable to add share %s to share.ldb\n"
			 "       err=%d [%s]\n", name, err, ldb_errstring(ldb)));
		if (err == LDB_ERR_NO_SUCH_OBJECT) {
			ret = NT_STATUS_OBJECT_NAME_NOT_FOUND;
		} else if (err == LDB_ERR_ENTRY_ALREADY_EXISTS) {
			ret = NT_STATUS_OBJECT_NAME_COLLISION;
		} else {
			ret = NT_STATUS_UNSUCCESSFUL;
		}
		goto done;
	}

	ret = NT_STATUS_OK;
done:
	talloc_free(tmp_ctx);
	return ret;
}
Esempio n. 18
0
static ssize_t xlat_tokenize_literal(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head,
				     int brace, char const **error)
{
	char *p, *q;
	xlat_exp_t *node;

	if (!*fmt) return 0;

	XLAT_DEBUG("LITERAL: %s", fmt);

	node = talloc_zero(ctx, xlat_exp_t);
	node->fmt = fmt;
	node->len = 0;
	node->type = XLAT_LITERAL;

	p = fmt;
	q = fmt;

	while (*p) {
		/*
		 *	Convert \n to it's literal representation.
		 */
		if (p[0] == '\\') switch (p[1]) {
			case 't':
				*(q++) = '\t';
				p += 2;
				node->len++;
				continue;

			case 'n':
				*(q++) = '\n';
				p += 2;
				node->len++;
				continue;

			case 'x':
				p += 2;
				if (!p[0] || !p[1]) {
					talloc_free(node);
					*error = "Hex expansion requires two hex digits";
					return -(p - fmt);
				}

				if (!fr_hex2bin(p, (uint8_t *) q, 2)) {
					talloc_free(node);
					*error = "Invalid hex characters";
					return -(p - fmt);
				}

				/*
				 *	Don't let people shoot themselves in the foot.
				 *	\x00 is forbidden.
				 */
				if (!*q) {
					talloc_free(node);
					*error = "Cannot add zero byte to printable string";
					return -(p - fmt);
				}

				p += 2;
				q++;
				node->len++;
				continue;

			default:
				*(q++) = *p;
				p += 2;
				node->len++;
				continue;	
			}

		/*
		 *	Process the expansion.
		 */
		if ((p[0] == '%') && (p[1] == '{')) {
			ssize_t slen;

			XLAT_DEBUG("LITERAL: %s --> %s", node->fmt, p);
			slen = xlat_tokenize_expansion(node, p, &node->next, error);
			if (slen <= 0) {
				talloc_free(node);
				return slen - (p - fmt);
			}
			*p = '\0'; /* end the literal */
			p += slen;

			rad_assert(node->next != NULL);

			/*
			 *	Short-circuit the recursive call.
			 *	This saves another function call and
			 *	memory allocation.
			 */
			if (!*p) break;

			/*
			 *	"foo %{User-Name} bar"
			 *	LITERAL		"foo "
			 *	EXPANSION	User-Name
			 *	LITERAL		" bar"
			 */
			slen = xlat_tokenize_literal(node->next, p, &(node->next->next), brace, error);
			rad_assert(slen != 0);
			if (slen < 0) {
				talloc_free(node);
				return slen - (p - fmt);
			}

			p += slen;
			break;	/* stop processing the string */
		}

		/*
		 *	Check for valid single-character expansions.
		 */
		if (p[0] == '%') {
			ssize_t slen;
			xlat_exp_t *next;

			if (!p[1] || !strchr("%dlmtDGHISTY", p[1])) {
					talloc_free(node);
					*error = "Invalid variable expansion";
					p++;
					return - (p - fmt);
			}

			XLAT_DEBUG("PERCENT: %s --> %c", node->fmt, p[1]);
			next = talloc_zero(node, xlat_exp_t);
			next->fmt = p + 1;
			next->len = 1;
			next->type = XLAT_PERCENT;

			node->next = next;
			*p = '\0';
			p += 2;

			if (!*p) break;

			/*
			 *	And recurse.
			 */
			slen = xlat_tokenize_literal(node->next, p, &(node->next->next), brace, error);
			rad_assert(slen != 0);
			if (slen < 0) {
				talloc_free(node);
				return slen - (p - fmt);
			}

			p += slen;
			break;	/* stop processing the string */
		}

		/*
		 *	If required, eat the brace.
		 */
		if (brace && (*p == '}')) {
			*q = '\0';
			p++;
			break;
		}

		*(q++) = *(p++);
		node->len++;
	}

	/*
	 *	Squash zero-width literals
	 */
	if (node->len > 0) {
		*head = node;

	} else {		
		(void) talloc_steal(ctx, node->next);
		*head = node->next;
		talloc_free(node);
	}

	return p - fmt;
}
Esempio n. 19
0
static NTSTATUS raw_smbcli_open(struct smbcli_tree *tree, const char *fname, int flags, int share_mode, int *fnum)
{
        union smb_open open_parms;
        uint_t openfn=0;
        uint_t accessmode=0;
        TALLOC_CTX *mem_ctx;
        NTSTATUS status;

        mem_ctx = talloc_init("raw_open");
        if (!mem_ctx) return NT_STATUS_NO_MEMORY;

        if (flags & O_CREAT) {
                openfn |= OPENX_OPEN_FUNC_CREATE;
        }
        if (!(flags & O_EXCL)) {
                if (flags & O_TRUNC) {
                        openfn |= OPENX_OPEN_FUNC_TRUNC;
                } else {
                        openfn |= OPENX_OPEN_FUNC_OPEN;
                }
        }

        accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);

        if ((flags & O_ACCMODE) == O_RDWR) {
                accessmode |= OPENX_MODE_ACCESS_RDWR;
        } else if ((flags & O_ACCMODE) == O_WRONLY) {
                accessmode |= OPENX_MODE_ACCESS_WRITE;
        } else if ((flags & O_ACCMODE) == O_RDONLY) {
                accessmode |= OPENX_MODE_ACCESS_READ;
	}

#if defined(O_SYNC)
        if ((flags & O_SYNC) == O_SYNC) {
                accessmode |= OPENX_MODE_WRITE_THRU;
        }
#endif

        if (share_mode == DENY_FCB) {
                accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
        }

        open_parms.openx.level = RAW_OPEN_OPENX;
        open_parms.openx.in.flags = 0;
        open_parms.openx.in.open_mode = accessmode;
        open_parms.openx.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
        open_parms.openx.in.file_attrs = 0;
        open_parms.openx.in.write_time = 0;
        open_parms.openx.in.open_func = openfn;
        open_parms.openx.in.size = 0;
        open_parms.openx.in.timeout = 0;
        open_parms.openx.in.fname = fname;

        status = smb_raw_open(tree, mem_ctx, &open_parms);
        talloc_free(mem_ctx);

        if (fnum && NT_STATUS_IS_OK(status)) {
                *fnum = open_parms.openx.out.file.fnum;
        }

        return status;
}
Esempio n. 20
0
int ldb_msg_find_duplicate_val(struct ldb_context *ldb,
			       TALLOC_CTX *mem_ctx,
			       const struct ldb_message_element *el,
			       struct ldb_val **duplicate,
			       uint32_t options)
{
	unsigned int i, j;
	struct ldb_val *val;

	if (options != 0) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	*duplicate = NULL;

	/*
	   If there are not many values, it is best to avoid the talloc
	   overhead and just do a brute force search.
	 */
	if (el->num_values < LDB_DUP_QUADRATIC_THRESHOLD) {
		for (j = 0; j < el->num_values; j++) {
			val = &el->values[j];
			for ( i = j + 1; i < el->num_values; i++) {
				if (ldb_val_equal_exact(val, &el->values[i])) {
					*duplicate = val;
					return LDB_SUCCESS;
				}
			}
		}
	} else {
		struct ldb_val *values;
		values = talloc_array(mem_ctx, struct ldb_val, el->num_values);
		if (values == NULL) {
			return LDB_ERR_OPERATIONS_ERROR;
		}

		memcpy(values, el->values,
		       el->num_values * sizeof(struct ldb_val));
		TYPESAFE_QSORT(values, el->num_values, ldb_val_cmp);
		for (i = 1; i < el->num_values; i++) {
			if (ldb_val_equal_exact(&values[i],
						&values[i - 1])) {
				/* find the original location */
				for (j = 0; j < el->num_values; j++) {
					if (ldb_val_equal_exact(&values[i],
								&el->values[j])
						) {
						*duplicate = &el->values[j];
						break;
					}
				}
				talloc_free(values);
				if (*duplicate == NULL) {
					/* how we got here, I don't know */
					return LDB_ERR_OPERATIONS_ERROR;
				}
				return LDB_SUCCESS;
			}
		}
		talloc_free(values);
	}
	return LDB_SUCCESS;
}
Esempio n. 21
0
bool torture_samba3_badpath(struct torture_context *torture)
{
	struct smbcli_state *cli_nt;
	struct smbcli_state *cli_dos;
	const char *fname = "test.txt";
	const char *fname1 = "test1.txt";
	const char *dirname = "testdir";
	char *fpath;
	char *fpath1;
	int fnum;
	NTSTATUS status;
	bool ret = true;
	TALLOC_CTX *mem_ctx;
	bool nt_status_support;

	if (!(mem_ctx = talloc_init("torture_samba3_badpath"))) {
		d_printf("talloc_init failed\n");
		return false;
	}

	nt_status_support = lp_nt_status_support(torture->lp_ctx);

	if (!lp_set_cmdline(torture->lp_ctx, "nt status support", "yes")) {
		printf("Could not set 'nt status support = yes'\n");
		goto fail;
	}

	if (!torture_open_connection(&cli_nt, torture, 0)) {
		goto fail;
	}

	if (!lp_set_cmdline(torture->lp_ctx, "nt status support", "no")) {
		printf("Could not set 'nt status support = yes'\n");
		goto fail;
	}

	if (!torture_open_connection(&cli_dos, torture, 1)) {
		goto fail;
	}

	if (!lp_set_cmdline(torture->lp_ctx, "nt status support",
			    nt_status_support ? "yes":"no")) {
		printf("Could not reset 'nt status support = yes'");
		goto fail;
	}

	smbcli_deltree(cli_nt->tree, dirname);

	status = smbcli_mkdir(cli_nt->tree, dirname);
	if (!NT_STATUS_IS_OK(status)) {
		d_printf("smbcli_mkdir failed: %s\n", nt_errstr(status));
		ret = false;
		goto done;
	}

	status = smbcli_chkpath(cli_nt->tree, dirname);
	CHECK_STATUS(status, NT_STATUS_OK);

	status = smbcli_chkpath(cli_nt->tree,
				talloc_asprintf(mem_ctx, "%s\\bla", dirname));
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_NOT_FOUND);

	status = smbcli_chkpath(cli_dos->tree,
				talloc_asprintf(mem_ctx, "%s\\bla", dirname));
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	status = smbcli_chkpath(cli_nt->tree,
				talloc_asprintf(mem_ctx, "%s\\bla\\blub",
						dirname));
	CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_NOT_FOUND);
	status = smbcli_chkpath(cli_dos->tree,
				talloc_asprintf(mem_ctx, "%s\\bla\\blub",
						dirname));
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	if (!(fpath = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname))) {
		goto fail;
	}
	fnum = smbcli_open(cli_nt->tree, fpath, O_RDWR | O_CREAT, DENY_NONE);
	if (fnum == -1) {
		d_printf("Could not create file %s: %s\n", fpath,
			 smbcli_errstr(cli_nt->tree));
		goto fail;
	}
	smbcli_close(cli_nt->tree, fnum);

	if (!(fpath1 = talloc_asprintf(mem_ctx, "%s\\%s", dirname, fname1))) {
		goto fail;
	}
	fnum = smbcli_open(cli_nt->tree, fpath1, O_RDWR | O_CREAT, DENY_NONE);
	if (fnum == -1) {
		d_printf("Could not create file %s: %s\n", fpath1,
			 smbcli_errstr(cli_nt->tree));
		goto fail;
	}
	smbcli_close(cli_nt->tree, fnum);

	/*
	 * Do a whole bunch of error code checks on chkpath
	 */

	status = smbcli_chkpath(cli_nt->tree, fpath);
	CHECK_STATUS(status, NT_STATUS_NOT_A_DIRECTORY);
	status = smbcli_chkpath(cli_dos->tree, fpath);
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	status = smbcli_chkpath(cli_nt->tree, "..");
	CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
	status = smbcli_chkpath(cli_dos->tree, "..");
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));

	status = smbcli_chkpath(cli_nt->tree, ".");
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_chkpath(cli_dos->tree, ".");
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	status = smbcli_chkpath(cli_nt->tree, "\t");
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_chkpath(cli_dos->tree, "\t");
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	status = smbcli_chkpath(cli_nt->tree, "\t\\bla");
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_chkpath(cli_dos->tree, "\t\\bla");
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	status = smbcli_chkpath(cli_nt->tree, "<");
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_chkpath(cli_dos->tree, "<");
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	status = smbcli_chkpath(cli_nt->tree, "<\\bla");
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_chkpath(cli_dos->tree, "<\\bla");
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRbadpath));

	/*
	 * .... And the same gang against getatr. Note that the DOS error codes
	 * differ....
	 */

	status = smbcli_getatr(cli_nt->tree, fpath, NULL, NULL, NULL);
	CHECK_STATUS(status, NT_STATUS_OK);
	status = smbcli_getatr(cli_dos->tree, fpath, NULL, NULL, NULL);
	CHECK_STATUS(status, NT_STATUS_OK);

	status = smbcli_getatr(cli_nt->tree, "..", NULL, NULL, NULL);
	CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
	status = smbcli_getatr(cli_dos->tree, "..", NULL, NULL, NULL);
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));

	status = smbcli_getatr(cli_nt->tree, ".", NULL, NULL, NULL);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_getatr(cli_dos->tree, ".", NULL, NULL, NULL);
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = smbcli_getatr(cli_nt->tree, "\t", NULL, NULL, NULL);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_getatr(cli_dos->tree, "\t", NULL, NULL, NULL);
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = smbcli_getatr(cli_nt->tree, "\t\\bla", NULL, NULL, NULL);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_getatr(cli_dos->tree, "\t\\bla", NULL, NULL, NULL);
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = smbcli_getatr(cli_nt->tree, "<", NULL, NULL, NULL);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_getatr(cli_dos->tree, "<", NULL, NULL, NULL);
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = smbcli_getatr(cli_nt->tree, "<\\bla", NULL, NULL, NULL);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
	status = smbcli_getatr(cli_dos->tree, "<\\bla", NULL, NULL, NULL);
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	/* Try the same set with openX. */

	status = raw_smbcli_open(cli_nt->tree, "..", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
	status = raw_smbcli_open(cli_dos->tree, "..", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidpath));

	status = raw_smbcli_open(cli_nt->tree, ".", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
	status = raw_smbcli_open(cli_dos->tree, ".", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = raw_smbcli_open(cli_nt->tree, "\t", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
	status = raw_smbcli_open(cli_dos->tree, "\t", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = raw_smbcli_open(cli_nt->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
	status = raw_smbcli_open(cli_dos->tree, "\t\\bla", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = raw_smbcli_open(cli_nt->tree, "<", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
	status = raw_smbcli_open(cli_dos->tree, "<", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	status = raw_smbcli_open(cli_nt->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_INVALID);
	status = raw_smbcli_open(cli_dos->tree, "<\\bla", O_RDONLY, DENY_NONE, NULL);
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRinvalidname));

	/* Let's test EEXIST error code mapping. */
	status = raw_smbcli_open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
	status = raw_smbcli_open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRfilexists));

	status = raw_smbcli_t2open(cli_nt->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
	if (!NT_STATUS_EQUAL(status, NT_STATUS_EAS_NOT_SUPPORTED)
	    || !torture_setting_bool(torture, "samba3", false)) {
		/* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
		CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
	}
	status = raw_smbcli_t2open(cli_dos->tree, fpath, O_RDONLY | O_CREAT| O_EXCL, DENY_NONE, NULL);
	if (!NT_STATUS_EQUAL(status, NT_STATUS_DOS(ERRDOS,ERReasnotsupported))
	    || !torture_setting_bool(torture, "samba3", false)) {
		/* Against samba3, treat EAS_NOT_SUPPORTED as acceptable */
		CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRfilexists));
	}

	status = raw_smbcli_ntcreate(cli_nt->tree, fpath, NULL);
	CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
	status = raw_smbcli_ntcreate(cli_dos->tree, fpath, NULL);
	CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRfilexists));

	/* Try the rename test. */
	{
		union smb_rename io;
		memset(&io, '\0', sizeof(io));
		io.rename.in.pattern1 = fpath1;
		io.rename.in.pattern2 = fpath;

		/* Try with SMBmv rename. */
		status = smb_raw_rename(cli_nt->tree, &io);
		CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
		status = smb_raw_rename(cli_dos->tree, &io);
		CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRrename));

		/* Try with NT rename. */
		io.generic.level = RAW_RENAME_NTRENAME;
		io.ntrename.in.old_name = fpath1;
		io.ntrename.in.new_name = fpath;
		io.ntrename.in.attrib = 0;
		io.ntrename.in.cluster_size = 0;
		io.ntrename.in.flags = RENAME_FLAG_RENAME;

		status = smb_raw_rename(cli_nt->tree, &io);
		CHECK_STATUS(status, NT_STATUS_OBJECT_NAME_COLLISION);
		status = smb_raw_rename(cli_dos->tree, &io);
		CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS,ERRrename));
	}

	goto done;

 fail:
	ret = false;

 done:
	if (cli_nt != NULL) {
		smbcli_deltree(cli_nt->tree, dirname);
		torture_close_connection(cli_nt);
	}
	if (cli_dos != NULL) {
		torture_close_connection(cli_dos);
	}
	talloc_free(mem_ctx);

	return ret;
}
Esempio n. 22
0
 krb5_error_code kinit_to_ccache(TALLOC_CTX *parent_ctx,
				 struct cli_credentials *credentials,
				 struct smb_krb5_context *smb_krb5_context,
				 krb5_ccache ccache) 
{
	krb5_error_code ret;
	const char *password;
	time_t kdc_time = 0;
	krb5_principal princ;
	int tries;
	TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);

	if (!mem_ctx) {
		return ENOMEM;
	}

	ret = principal_from_credentials(mem_ctx, credentials, smb_krb5_context, &princ);
	if (ret) {
		talloc_free(mem_ctx);
		return ret;
	}

	password = cli_credentials_get_password(credentials);

	tries = 2;
	while (tries--) {
		if (password) {
			ret = kerberos_kinit_password_cc(smb_krb5_context->krb5_context, ccache, 
							 princ, 
							 password, NULL, &kdc_time);
		} else {
			/* No password available, try to use a keyblock instead */
			
			krb5_keyblock keyblock;
			const struct samr_Password *mach_pwd;
			mach_pwd = cli_credentials_get_nt_hash(credentials, mem_ctx);
			if (!mach_pwd) {
				talloc_free(mem_ctx);
				DEBUG(1, ("kinit_to_ccache: No password available for kinit\n"));
				return EINVAL;
			}
			ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
						 ETYPE_ARCFOUR_HMAC_MD5,
						 mach_pwd->hash, sizeof(mach_pwd->hash), 
						 &keyblock);
			
			if (ret == 0) {
				ret = kerberos_kinit_keyblock_cc(smb_krb5_context->krb5_context, ccache, 
								 princ,
								 &keyblock, NULL, &kdc_time);
				krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &keyblock);
			}
		}

		if (ret == KRB5KRB_AP_ERR_SKEW || ret == KRB5_KDCREP_SKEW) {
			/* Perhaps we have been given an invalid skew, so try again without it */
			time_t t = time(NULL);
			krb5_set_real_time(smb_krb5_context->krb5_context, t, 0);
		} else {
			/* not a skew problem */
			break;
		}
	}

	if (ret == KRB5KRB_AP_ERR_SKEW || ret == KRB5_KDCREP_SKEW) {
		DEBUG(1,("kinit for %s failed (%s)\n", 
			 cli_credentials_get_principal(credentials, mem_ctx), 
			 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
						    ret, mem_ctx)));
		talloc_free(mem_ctx);
		return ret;
	}

	/* cope with ticket being in the future due to clock skew */
	if ((unsigned)kdc_time > time(NULL)) {
		time_t t = time(NULL);
		int time_offset =(unsigned)kdc_time-t;
		DEBUG(4,("Advancing clock by %d seconds to cope with clock skew\n", time_offset));
		krb5_set_real_time(smb_krb5_context->krb5_context, t + time_offset + 1, 0);
	}
	
	if (ret == KRB5KDC_ERR_PREAUTH_FAILED && cli_credentials_wrong_password(credentials)) {
		ret = kinit_to_ccache(parent_ctx,
				      credentials,
				      smb_krb5_context,
				      ccache); 
	}
	if (ret) {
		DEBUG(1,("kinit for %s failed (%s)\n", 
			 cli_credentials_get_principal(credentials, mem_ctx), 
			 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
						    ret, mem_ctx)));
		talloc_free(mem_ctx);
		return ret;
	} 
	talloc_free(mem_ctx);
	return 0;
}
Esempio n. 23
0
/*
  called by samr_CreateDomainGroup and pdb_samba4
*/
NTSTATUS dsdb_add_domain_group(struct ldb_context *ldb,
			       TALLOC_CTX *mem_ctx,
			       const char *groupname,
			       struct dom_sid **sid,
			       struct ldb_dn **dn)
{
	const char *name;
	struct ldb_message *msg;
	struct dom_sid *group_sid;
	int ret;

	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);

	/* check if the group already exists */
	name = samdb_search_string(ldb, tmp_ctx, NULL,
				   "sAMAccountName",
				   "(&(sAMAccountName=%s)(objectclass=group))",
				   ldb_binary_encode_string(tmp_ctx, groupname));
	if (name != NULL) {
		return NT_STATUS_GROUP_EXISTS;
	}

	msg = ldb_msg_new(tmp_ctx);
	if (msg == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	/* add core elements to the ldb_message for the user */
	msg->dn = ldb_dn_copy(tmp_ctx, ldb_get_default_basedn(ldb));
	ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=Users", groupname);
	if (!msg->dn) {
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}
	ldb_msg_add_string(msg, "sAMAccountName", groupname);
	ldb_msg_add_string(msg, "objectClass", "group");

	/* create the group */
	ret = ldb_add(ldb, msg);
	switch (ret) {
	case  LDB_SUCCESS:
		break;
	case  LDB_ERR_ENTRY_ALREADY_EXISTS:
		DEBUG(0,("Failed to create group record %s: %s\n",
			 ldb_dn_get_linearized(msg->dn),
			 ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return NT_STATUS_GROUP_EXISTS;
	case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
		DEBUG(0,("Failed to create group record %s: %s\n",
			 ldb_dn_get_linearized(msg->dn),
			 ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return NT_STATUS_ACCESS_DENIED;
	default:
		DEBUG(0,("Failed to create group record %s: %s\n",
			 ldb_dn_get_linearized(msg->dn),
			 ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	/* retrieve the sid for the group just created */
	group_sid = samdb_search_dom_sid(ldb, tmp_ctx,
					 msg->dn, "objectSid", NULL);
	if (group_sid == NULL) {
		return NT_STATUS_UNSUCCESSFUL;
	}

	*dn = talloc_steal(mem_ctx, msg->dn);
	*sid = talloc_steal(mem_ctx, group_sid);
	talloc_free(tmp_ctx);
	return NT_STATUS_OK;
}
Esempio n. 24
0
static krb5_error_code keytab_add_keys(TALLOC_CTX *parent_ctx,
				       const char *princ_string,
				       krb5_principal princ,
				       krb5_principal salt_princ,
				       int kvno,
				       const char *password_s,
				       struct smb_krb5_context *smb_krb5_context,
				       const char **enctype_strings,
				       krb5_keytab keytab)
{
	int i;
	krb5_error_code ret;
	krb5_data password;
	TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
	if (!mem_ctx) {
		return ENOMEM;
	}

	password.data = discard_const_p(char *, password_s);
	password.length = strlen(password_s);

	for (i=0; enctype_strings[i]; i++) {
		krb5_keytab_entry entry;
		krb5_enctype enctype;
		ret = krb5_string_to_enctype(smb_krb5_context->krb5_context, enctype_strings[i], &enctype);
		if (ret != 0) {
			DEBUG(1, ("Failed to interpret %s as a krb5 encryption type: %s\n",				  
				  enctype_strings[i],
				  smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
							     ret, mem_ctx)));
			talloc_free(mem_ctx);
			return ret;
		}
		ret = create_kerberos_key_from_string(smb_krb5_context->krb5_context, 
						      salt_princ, &password, &entry.keyblock, enctype);
		if (ret != 0) {
			talloc_free(mem_ctx);
			return ret;
		}

                entry.principal = princ;
                entry.vno       = kvno;
		ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, keytab, &entry);
		if (ret != 0) {
			DEBUG(1, ("Failed to add %s entry for %s(kvno %d) to keytab: %s\n",
				  enctype_strings[i],
				  princ_string,
				  kvno,
				  smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
							     ret, mem_ctx)));
			talloc_free(mem_ctx);
			krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
			return ret;
		}

		DEBUG(5, ("Added %s(kvno %d) to keytab (%s)\n", 
			  princ_string, kvno,
			  enctype_strings[i]));
		
		krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
	}
	talloc_free(mem_ctx);
	return 0;
}
Esempio n. 25
0
NTSTATUS dsdb_add_domain_alias(struct ldb_context *ldb,
			       TALLOC_CTX *mem_ctx,
			       const char *alias_name,
			       struct dom_sid **sid,
			       struct ldb_dn **dn)
{
	const char *name;
	struct ldb_message *msg;
	struct dom_sid *alias_sid;
	int ret;

	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);

	if (ldb_transaction_start(ldb) != LDB_SUCCESS) {
		DEBUG(0, ("Failed to start transaction in dsdb_add_domain_alias(): %s\n", ldb_errstring(ldb)));
		return NT_STATUS_INTERNAL_ERROR;
	}

	/* Check if alias already exists */
	name = samdb_search_string(ldb, tmp_ctx, NULL,
				   "sAMAccountName",
				   "(sAMAccountName=%s)(objectclass=group))",
				   ldb_binary_encode_string(mem_ctx, alias_name));

	if (name != NULL) {
		talloc_free(tmp_ctx);
		ldb_transaction_cancel(ldb);
		return NT_STATUS_ALIAS_EXISTS;
	}

	msg = ldb_msg_new(tmp_ctx);
	if (msg == NULL) {
		talloc_free(tmp_ctx);
		ldb_transaction_cancel(ldb);
		return NT_STATUS_NO_MEMORY;
	}

	/* add core elements to the ldb_message for the alias */
	msg->dn = ldb_dn_copy(mem_ctx, ldb_get_default_basedn(ldb));
	ldb_dn_add_child_fmt(msg->dn, "CN=%s,CN=Users", alias_name);
	if (!msg->dn) {
		talloc_free(tmp_ctx);
		ldb_transaction_cancel(ldb);
		return NT_STATUS_NO_MEMORY;
	}

	ldb_msg_add_string(msg, "sAMAccountName", alias_name);
	ldb_msg_add_string(msg, "objectClass", "group");
	samdb_msg_add_int(ldb, mem_ctx, msg, "groupType", GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);

	/* create the alias */
	ret = ldb_add(ldb, msg);
	switch (ret) {
	case LDB_SUCCESS:
		break;
	case LDB_ERR_ENTRY_ALREADY_EXISTS:
		talloc_free(tmp_ctx);
		ldb_transaction_cancel(ldb);
		return NT_STATUS_ALIAS_EXISTS;
	case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
		talloc_free(tmp_ctx);
		ldb_transaction_cancel(ldb);
		return NT_STATUS_ACCESS_DENIED;
	default:
		DEBUG(0,("Failed to create alias record %s: %s\n",
			 ldb_dn_get_linearized(msg->dn),
			 ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		ldb_transaction_cancel(ldb);
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	/* retrieve the sid for the alias just created */
	alias_sid = samdb_search_dom_sid(ldb, tmp_ctx,
					 msg->dn, "objectSid", NULL);

	if (ldb_transaction_commit(ldb) != LDB_SUCCESS) {
		DEBUG(0, ("Failed to commit transaction in dsdb_add_domain_alias(): %s\n",
			  ldb_errstring(ldb)));
		return NT_STATUS_INTERNAL_ERROR;
	}

	*dn = talloc_steal(mem_ctx, msg->dn);
	*sid = talloc_steal(mem_ctx, alias_sid);
	talloc_free(tmp_ctx);


	return NT_STATUS_OK;
}
Esempio n. 26
0
static int create_keytab(TALLOC_CTX *parent_ctx,
			 struct cli_credentials *machine_account,
			 struct smb_krb5_context *smb_krb5_context,
			 const char **enctype_strings,
			 krb5_keytab keytab,
			 BOOL add_old) 
{
	krb5_error_code ret;
	const char *password_s;
	const char *old_secret;
	int kvno;
	krb5_principal salt_princ;
	krb5_principal princ;
	const char *princ_string;

	TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
	if (!mem_ctx) {
		return ENOMEM;
	}

	princ_string = cli_credentials_get_principal(machine_account, mem_ctx);
	/* Get the principal we will store the new keytab entries under */
	ret = principal_from_credentials(mem_ctx, machine_account, smb_krb5_context, &princ);
	if (ret) {
		DEBUG(1,("create_keytab: makeing krb5 principal failed (%s)\n",
			 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
						    ret, mem_ctx)));
		talloc_free(mem_ctx);
		return ret;
	}

	/* The salt used to generate these entries may be different however, fetch that */
	ret = salt_principal_from_credentials(mem_ctx, machine_account, 
					      smb_krb5_context, 
					      &salt_princ);
	if (ret) {
		DEBUG(1,("create_keytab: makeing salt principal failed (%s)\n",
			 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
						    ret, mem_ctx)));
		talloc_free(mem_ctx);
		return ret;
	}

	/* Finally, do the dance to get the password to put in the entry */
	password_s = cli_credentials_get_password(machine_account);
	if (!password_s) {
		krb5_keytab_entry entry;
		const struct samr_Password *mach_pwd;

		if (!str_list_check(enctype_strings, "arcfour-hmac-md5")) {
			DEBUG(1, ("Asked to create keytab, but with only an NT hash supplied, "
				  "but not listing arcfour-hmac-md5 as an enc type to include in the keytab!\n"));
			talloc_free(mem_ctx);
			return EINVAL;
		}

		/* If we don't have the plaintext password, try for
		 * the MD4 password hash */
		mach_pwd = cli_credentials_get_nt_hash(machine_account, mem_ctx);
		if (!mach_pwd) {
			/* OK, nothing to do here */
			talloc_free(mem_ctx);
			return 0;
		}
		ret = krb5_keyblock_init(smb_krb5_context->krb5_context,
					 ETYPE_ARCFOUR_HMAC_MD5,
					 mach_pwd->hash, sizeof(mach_pwd->hash), 
					 &entry.keyblock);
		if (ret) {
			DEBUG(1, ("create_keytab: krb5_keyblock_init failed: %s\n",
				  smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
							     ret, mem_ctx)));
			talloc_free(mem_ctx);
			return ret;
		}

		entry.principal = princ;
		entry.vno       = cli_credentials_get_kvno(machine_account);
		ret = krb5_kt_add_entry(smb_krb5_context->krb5_context, keytab, &entry);
		if (ret) {
			DEBUG(1, ("Failed to add ARCFOUR_HMAC (only) entry for %s to keytab: %s",
				  cli_credentials_get_principal(machine_account, mem_ctx), 
				  smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
							     ret, mem_ctx)));
			talloc_free(mem_ctx);
			krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);
			return ret;
		}
		
		DEBUG(5, ("Added %s(kvno %d) to keytab (arcfour-hmac-md5)\n", 
			  cli_credentials_get_principal(machine_account, mem_ctx),
			  cli_credentials_get_kvno(machine_account)));

		krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &entry.keyblock);

		/* Can't go any further, we only have this one key */
		talloc_free(mem_ctx);
		return 0;
	}
	
	kvno = cli_credentials_get_kvno(machine_account);
	/* good, we actually have the real plaintext */
	ret = keytab_add_keys(mem_ctx, princ_string, princ, salt_princ, 
			      kvno, password_s, smb_krb5_context, 
			      enctype_strings, keytab);
	if (!ret) {
		talloc_free(mem_ctx);
		return ret;
	}

	if (!add_old || kvno == 0) {
		talloc_free(mem_ctx);
		return 0;
	}

	old_secret = cli_credentials_get_old_password(machine_account);
	if (!old_secret) {
		talloc_free(mem_ctx);
		return 0;
	}
	
	ret = keytab_add_keys(mem_ctx, princ_string, princ, salt_princ, 
			      kvno - 1, old_secret, smb_krb5_context, 
			      enctype_strings, keytab);
	if (!ret) {
		talloc_free(mem_ctx);
		return ret;
	}

	talloc_free(mem_ctx);
	return 0;
}
Esempio n. 27
0
NTSTATUS dsdb_lookup_rids(struct ldb_context *ldb,
			  TALLOC_CTX *mem_ctx,
			  const struct dom_sid *domain_sid,
			  unsigned int num_rids,
			  uint32_t *rids,
			  const char **names,
			  enum lsa_SidType *lsa_attrs)
{
	const char *attrs[] = { "sAMAccountType", "sAMAccountName", NULL };
	unsigned int i, num_mapped;

	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);

	num_mapped = 0;

	for (i=0; i<num_rids; i++) {
		struct ldb_message *msg;
		struct ldb_dn *dn;
		uint32_t attr;
		int rc;

		lsa_attrs[i] = SID_NAME_UNKNOWN;

		dn = ldb_dn_new_fmt(tmp_ctx, ldb, "<SID=%s>",
				    dom_sid_string(tmp_ctx,
						   dom_sid_add_rid(tmp_ctx, domain_sid,
								   rids[i])));
		if (dn == NULL) {
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}
		rc = dsdb_search_one(ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "samAccountName=*");
		if (rc == LDB_ERR_NO_SUCH_OBJECT) {
			continue;
		} else if (rc != LDB_SUCCESS) {
			talloc_free(tmp_ctx);
			return NT_STATUS_INTERNAL_DB_CORRUPTION;
		}

		names[i] = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);
		if (names[i] == NULL) {
			DEBUG(10, ("no samAccountName\n"));
			continue;
		}
		talloc_steal(names, names[i]);
		attr = ldb_msg_find_attr_as_uint(msg, "samAccountType", 0);
		lsa_attrs[i] = ds_atype_map(attr);
		if (lsa_attrs[i] == SID_NAME_UNKNOWN) {
			continue;
		}
		num_mapped += 1;
	}
	talloc_free(tmp_ctx);

	if (num_mapped == 0) {
		return NT_STATUS_NONE_MAPPED;
	}
	if (num_mapped < num_rids) {
		return STATUS_SOME_UNMAPPED;
	}
	return NT_STATUS_OK;
}
Esempio n. 28
0
static krb5_error_code remove_old_entries(TALLOC_CTX *parent_ctx,
					  struct cli_credentials *machine_account,
					  struct smb_krb5_context *smb_krb5_context,
					  krb5_keytab keytab, BOOL *found_previous)
{
	krb5_error_code ret, ret2;
	krb5_kt_cursor cursor;
	krb5_principal princ;
	int kvno;
	TALLOC_CTX *mem_ctx = talloc_new(parent_ctx);
	const char *princ_string;
	if (!mem_ctx) {
		return ENOMEM;
	}

	*found_previous = False;
	princ_string = cli_credentials_get_principal(machine_account, mem_ctx);

	/* Get the principal we will store the new keytab entries under */
	ret = principal_from_credentials(mem_ctx, machine_account, smb_krb5_context, &princ);
	if (ret) {
		DEBUG(1,("update_keytab: makeing krb5 principal failed (%s)\n",
			 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
						    ret, mem_ctx)));
		talloc_free(mem_ctx);
		return ret;
	}

	kvno = cli_credentials_get_kvno(machine_account);

	/* for each entry in the keytab */
	ret = krb5_kt_start_seq_get(smb_krb5_context->krb5_context, keytab, &cursor);
	switch (ret) {
	case 0:
		break;
	case HEIM_ERR_OPNOTSUPP:
	case ENOENT:
	case KRB5_KT_END:
		/* no point enumerating if there isn't anything here */
		talloc_free(mem_ctx);
		return 0;
	default:
		DEBUG(1,("failed to open keytab for read of old entries: %s\n",
			 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
						    ret, mem_ctx)));
		talloc_free(mem_ctx);
		return ret;
	}

	while (!ret) {
		krb5_keytab_entry entry;
		ret = krb5_kt_next_entry(smb_krb5_context->krb5_context, keytab, &entry, &cursor);
		if (ret) {
			break;
		}
		/* if it matches our principal */
		if (!krb5_kt_compare(smb_krb5_context->krb5_context, &entry, princ, 0, 0)) {
			/* Free the entry, it wasn't the one we were looking for anyway */
			krb5_kt_free_entry(smb_krb5_context->krb5_context, &entry);
			continue;
		}

		/* delete it, if it is not kvno -1 */
		if (entry.vno != (kvno - 1 )) {
			/* Release the enumeration.  We are going to
			 * have to start this from the top again,
			 * because deletes during enumeration may not
			 * always be consistant.
			 *
			 * Also, the enumeration locks a FILE: keytab
			 */
		
			krb5_kt_end_seq_get(smb_krb5_context->krb5_context, keytab, &cursor);

			ret = krb5_kt_remove_entry(smb_krb5_context->krb5_context, keytab, &entry);
			krb5_kt_free_entry(smb_krb5_context->krb5_context, &entry);

			/* Deleted: Restart from the top */
			ret2 = krb5_kt_start_seq_get(smb_krb5_context->krb5_context, keytab, &cursor);
			if (ret2) {
				krb5_kt_free_entry(smb_krb5_context->krb5_context, &entry);
				DEBUG(1,("failed to restart enumeration of keytab: %s\n",
					 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
								    ret, mem_ctx)));
				
				talloc_free(mem_ctx);
				return ret2;
			}

			if (ret) {
				break;
			}
			
		} else {
			*found_previous = True;
		}
		
		/* Free the entry, we don't need it any more */
		krb5_kt_free_entry(smb_krb5_context->krb5_context, &entry);
		
		
	}
	krb5_kt_end_seq_get(smb_krb5_context->krb5_context, keytab, &cursor);

	switch (ret) {
	case 0:
		break;
	case ENOENT:
	case KRB5_KT_END:
		ret = 0;
		break;
	default:
		DEBUG(1,("failed in deleting old entries for principal: %s: %s\n",
			 princ_string, 
			 smb_get_krb5_error_message(smb_krb5_context->krb5_context, 
						    ret, mem_ctx)));
	}
	talloc_free(mem_ctx);
	return ret;
}
Esempio n. 29
0
int
main (int argc, char *argv[])
{
    void *local;
    command_t *command;
    alias_t *alias;
    unsigned int i, j;
    const char **argv_local;

    talloc_enable_null_tracking ();

    local = talloc_new (NULL);

    g_mime_init (0);
    g_type_init ();

    if (argc == 1)
	return notmuch (local);

    if (STRNCMP_LITERAL (argv[1], "--help") == 0)
	return notmuch_help_command (NULL, 0, NULL);

    if (STRNCMP_LITERAL (argv[1], "--version") == 0) {
	printf ("notmuch " STRINGIFY(NOTMUCH_VERSION) "\n");
	return 0;
    }

    for (i = 0; i < ARRAY_SIZE (aliases); i++) {
	alias = &aliases[i];

	if (strcmp (argv[1], alias->name) == 0)
	{
	    int substitutions;

	    argv_local = talloc_size (local, sizeof (char *) *
				      (argc + MAX_ALIAS_SUBSTITUTIONS - 1));
	    if (argv_local == NULL) {
		fprintf (stderr, "Out of memory.\n");
		return 1;
	    }

	    /* Copy all substution arguments from the alias. */
	    argv_local[0] = argv[0];
	    for (j = 0; j < MAX_ALIAS_SUBSTITUTIONS; j++) {
		if (alias->substitutions[j] == NULL)
		    break;
		argv_local[j+1] = alias->substitutions[j];
	    }
	    substitutions = j;

	    /* And copy all original arguments (skipping the argument
	     * that matched the alias of course. */
	    for (j = 2; j < (unsigned) argc; j++) {
		argv_local[substitutions+j-1] = argv[j];
	    }

	    argc += substitutions - 1;
	    argv = (char **) argv_local;
	}
    }

    for (i = 0; i < ARRAY_SIZE (commands); i++) {
	command = &commands[i];

	if (strcmp (argv[1], command->name) == 0)
	    return (command->function) (local, argc - 2, &argv[2]);
    }

    fprintf (stderr, "Error: Unknown command '%s' (see \"notmuch help\")\n",
	     argv[1]);

    talloc_free (local);

    return 1;
}
Esempio n. 30
0
static NTSTATUS check_samba4_security(const struct auth_context *auth_context,
				      void *my_private_data,
				      TALLOC_CTX *mem_ctx,
				      const struct auth_usersupplied_info *user_info,
				      struct auth_serversupplied_info **server_info)
{
	TALLOC_CTX *frame = talloc_stackframe();
	struct netr_SamInfo3 *info3 = NULL;
	NTSTATUS nt_status;
	struct auth_user_info_dc *user_info_dc;
	struct auth4_context *auth4_context;
	struct loadparm_context *lp_ctx;

	lp_ctx = loadparm_init_s3(frame, loadparm_s3_context());
	if (lp_ctx == NULL) {
		DEBUG(10, ("loadparm_init_s3 failed\n"));
		talloc_free(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	/* We create a private tevent context here to avoid nested loops in
	 * the s3 one, as that may not be expected */
	nt_status = auth_context_create(mem_ctx,
					s4_event_context_init(frame), NULL, 
					lp_ctx,
					&auth4_context);
	NT_STATUS_NOT_OK_RETURN(nt_status);
		
	nt_status = auth_context_set_challenge(auth4_context, auth_context->challenge.data, "auth_samba4");
	NT_STATUS_NOT_OK_RETURN_AND_FREE(nt_status, auth4_context);

	nt_status = auth_check_password(auth4_context, auth4_context, user_info, &user_info_dc);
	NT_STATUS_NOT_OK_RETURN_AND_FREE(nt_status, auth4_context);
	
	nt_status = auth_convert_user_info_dc_saminfo3(mem_ctx,
						       user_info_dc,
						       &info3);
	if (NT_STATUS_IS_OK(nt_status)) {
		/* We need the strings from the server_info to be valid as long as the info3 is around */
		talloc_steal(info3, user_info_dc);
	}
	talloc_free(auth4_context);

	if (!NT_STATUS_IS_OK(nt_status)) {
		goto done;
	}

	nt_status = make_server_info_info3(mem_ctx, user_info->client.account_name,
					   user_info->mapped.domain_name, server_info,
					info3);
	if (!NT_STATUS_IS_OK(nt_status)) {
		DEBUG(10, ("make_server_info_info3 failed: %s\n",
			   nt_errstr(nt_status)));
		TALLOC_FREE(frame);
		return nt_status;
	}

	nt_status = NT_STATUS_OK;

 done:
	TALLOC_FREE(frame);
	return nt_status;
}