summaryrefslogtreecommitdiff
path: root/source3/libsmb
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libsmb')
-rw-r--r--source3/libsmb/clifile.c144
-rw-r--r--source3/libsmb/clikrb5.c9
-rw-r--r--source3/libsmb/clispnego.c35
-rw-r--r--source3/libsmb/dsgetdcname.c2
-rw-r--r--source3/libsmb/trusts_util.c58
5 files changed, 217 insertions, 31 deletions
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index b15aa8d998..5eb8bd471b 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -5027,3 +5027,147 @@ NTSTATUS cli_posix_rmdir(struct cli_state *cli, const char *fname)
}
return status;
}
+
+/****************************************************************************
+ filechangenotify
+****************************************************************************/
+
+struct cli_notify_state {
+ uint8_t setup[8];
+ uint32_t num_changes;
+ struct notify_change *changes;
+};
+
+static void cli_notify_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli, uint16_t fnum,
+ uint32_t buffer_size,
+ uint32_t completion_filter, bool recursive)
+{
+ struct tevent_req *req, *subreq;
+ struct cli_notify_state *state;
+
+ req = tevent_req_create(mem_ctx, &state, struct cli_notify_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ SIVAL(state->setup, 0, completion_filter);
+ SSVAL(state->setup, 4, fnum);
+ SSVAL(state->setup, 6, recursive);
+
+ subreq = cli_trans_send(
+ state, /* mem ctx. */
+ ev, /* event ctx. */
+ cli, /* cli_state. */
+ SMBnttrans, /* cmd. */
+ NULL, /* pipe name. */
+ -1, /* fid. */
+ NT_TRANSACT_NOTIFY_CHANGE, /* function. */
+ 0, /* flags. */
+ (uint16_t *)state->setup, /* setup. */
+ 4, /* num setup uint16_t words. */
+ 0, /* max returned setup. */
+ NULL, /* param. */
+ 0, /* num param. */
+ buffer_size, /* max returned param. */
+ NULL, /* data. */
+ 0, /* num data. */
+ 0); /* max returned data. */
+
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, cli_notify_done, req);
+ return req;
+}
+
+static void cli_notify_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_notify_state *state = tevent_req_data(
+ req, struct cli_notify_state);
+ NTSTATUS status;
+ uint8_t *params;
+ uint32_t i, ofs, num_params;
+
+ status = cli_trans_recv(subreq, talloc_tos(), NULL, NULL,
+ &params, &num_params, NULL, NULL);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status)));
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ state->num_changes = 0;
+ ofs = 0;
+
+ while (num_params - ofs > 12) {
+ uint32_t len = IVAL(params, ofs);
+ state->num_changes += 1;
+
+ if ((len == 0) || (ofs+len >= num_params)) {
+ break;
+ }
+ ofs += len;
+ }
+
+ state->changes = talloc_array(state, struct notify_change,
+ state->num_changes);
+ if (tevent_req_nomem(state->changes, req)) {
+ TALLOC_FREE(params);
+ return;
+ }
+
+ ofs = 0;
+
+ for (i=0; i<state->num_changes; i++) {
+ uint32_t next = IVAL(params, ofs);
+ uint32_t len = IVAL(params, ofs+8);
+ ssize_t ret;
+ char *name;
+
+ if ((next != 0) && (len+12 != next)) {
+ TALLOC_FREE(params);
+ tevent_req_nterror(
+ req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
+ }
+
+ state->changes[i].action = IVAL(params, ofs+4);
+ ret = clistr_pull_talloc(params, (char *)params, &name,
+ params+ofs+12, len,
+ STR_TERMINATE|STR_UNICODE);
+ if (ret == -1) {
+ TALLOC_FREE(params);
+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+ return;
+ }
+ state->changes[i].name = name;
+ ofs += next;
+ }
+
+ TALLOC_FREE(params);
+ tevent_req_done(req);
+}
+
+NTSTATUS cli_notify_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ uint32_t *pnum_changes,
+ struct notify_change **pchanges)
+{
+ struct cli_notify_state *state = tevent_req_data(
+ req, struct cli_notify_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+
+ *pnum_changes = state->num_changes;
+ *pchanges = talloc_move(mem_ctx, &state->changes);
+ return NT_STATUS_OK;
+}
diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c
index 152c23bd15..145e30beb3 100644
--- a/source3/libsmb/clikrb5.c
+++ b/source3/libsmb/clikrb5.c
@@ -1858,6 +1858,15 @@ static krb5_error_code ads_krb5_get_fwd_ticket( krb5_context context,
char *pChksum = NULL;
char *p = NULL;
+/* MIT krb5 1.7beta3 (in Ubuntu Karmic) is missing the prototype,
+ but still has the symbol */
+#if !HAVE_DECL_KRB5_AUTH_CON_SET_REQ_CKSUMTYPE
+krb5_error_code krb5_auth_con_set_req_cksumtype(
+ krb5_context context,
+ krb5_auth_context auth_context,
+ krb5_cksumtype cksumtype);
+#endif
+
ZERO_STRUCT(fwdData);
ZERO_STRUCTP(authenticator);
diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c
index 5d7e43d941..e20749b3e8 100644
--- a/source3/libsmb/clispnego.c
+++ b/source3/libsmb/clispnego.c
@@ -495,31 +495,28 @@ DATA_BLOB spnego_gen_auth(DATA_BLOB blob)
*/
bool spnego_parse_auth(DATA_BLOB blob, DATA_BLOB *auth)
{
- ASN1_DATA *data;
+ ssize_t len;
+ struct spnego_data token;
- data = asn1_init(talloc_tos());
- if (data == NULL) {
+ len = spnego_read_data(talloc_tos(), blob, &token);
+ if (len == -1) {
+ DEBUG(3,("spnego_parse_auth: spnego_read_data failed\n"));
return false;
}
- asn1_load(data, blob);
- asn1_start_tag(data, ASN1_CONTEXT(1));
- asn1_start_tag(data, ASN1_SEQUENCE(0));
- asn1_start_tag(data, ASN1_CONTEXT(2));
- asn1_read_OctetString(data, talloc_autofree_context(), auth);
- asn1_end_tag(data);
- asn1_end_tag(data);
- asn1_end_tag(data);
-
- if (data->has_error) {
- DEBUG(3,("spnego_parse_auth failed at %d\n", (int)data->ofs));
- data_blob_free(auth);
- asn1_free(data);
- return False;
+ if (token.type != SPNEGO_NEG_TOKEN_TARG) {
+ DEBUG(3,("spnego_parse_auth: wrong token type: %d\n",
+ token.type));
+ spnego_free_data(&token);
+ return false;
}
- asn1_free(data);
- return True;
+ *auth = data_blob_talloc(talloc_tos(),
+ token.negTokenTarg.responseToken.data,
+ token.negTokenTarg.responseToken.length);
+ spnego_free_data(&token);
+
+ return true;
}
/*
diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c
index 98b65942e4..180547063a 100644
--- a/source3/libsmb/dsgetdcname.c
+++ b/source3/libsmb/dsgetdcname.c
@@ -686,7 +686,7 @@ static NTSTATUS make_domain_controller_info(TALLOC_CTX *mem_ctx,
if (forest_name && *forest_name) {
info->forest_name = talloc_strdup(mem_ctx, forest_name);
NT_STATUS_HAVE_NO_MEMORY(info->forest_name);
- flags |= DS_DNS_FOREST;
+ flags |= DS_DNS_FOREST_ROOT;
}
info->dc_flags = flags;
diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c
index 929816e92d..584217d3f1 100644
--- a/source3/libsmb/trusts_util.c
+++ b/source3/libsmb/trusts_util.c
@@ -29,13 +29,22 @@
NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
const char *domain,
+ const char *account_name,
unsigned char orig_trust_passwd_hash[16],
- uint32 sec_channel_type)
+ enum netr_SchannelType sec_channel_type)
{
unsigned char new_trust_passwd_hash[16];
char *new_trust_passwd;
NTSTATUS nt_status;
-
+
+ switch (sec_channel_type) {
+ case SEC_CHAN_WKSTA:
+ case SEC_CHAN_DOMAIN:
+ break;
+ default:
+ return NT_STATUS_NOT_SUPPORTED;
+ }
+
/* Create a random machine account password */
new_trust_passwd = generate_random_str(mem_ctx, DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
@@ -43,15 +52,16 @@ NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *m
DEBUG(0, ("talloc_strdup failed\n"));
return NT_STATUS_NO_MEMORY;
}
-
+
E_md4hash(new_trust_passwd, new_trust_passwd_hash);
nt_status = rpccli_netlogon_set_trust_password(cli, mem_ctx,
+ account_name,
orig_trust_passwd_hash,
new_trust_passwd,
new_trust_passwd_hash,
sec_channel_type);
-
+
if (NT_STATUS_IS_OK(nt_status)) {
DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n",
current_timestring(debug_ctx(), False)));
@@ -59,8 +69,33 @@ NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *m
* Return the result of trying to write the new password
* back into the trust account file.
*/
- if (!secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type)) {
- nt_status = NT_STATUS_UNSUCCESSFUL;
+
+ switch (sec_channel_type) {
+
+ case SEC_CHAN_WKSTA:
+ if (!secrets_store_machine_password(new_trust_passwd, domain, sec_channel_type)) {
+ nt_status = NT_STATUS_UNSUCCESSFUL;
+ }
+ break;
+
+ case SEC_CHAN_DOMAIN: {
+ char *pwd;
+ struct dom_sid sid;
+ time_t pass_last_set_time;
+
+ /* we need to get the sid first for the
+ * pdb_set_trusteddom_pw call */
+
+ if (!pdb_get_trusteddom_pw(domain, &pwd, &sid, &pass_last_set_time)) {
+ nt_status = NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE;
+ }
+ if (!pdb_set_trusteddom_pw(domain, new_trust_passwd, &sid)) {
+ nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ break;
+ }
+ default:
+ break;
}
}
@@ -78,16 +113,17 @@ NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli,
const char *domain)
{
unsigned char old_trust_passwd_hash[16];
- uint32 sec_channel_type = 0;
+ enum netr_SchannelType sec_channel_type = SEC_CHAN_NULL;
+ const char *account_name;
- if (!secrets_fetch_trust_account_password(domain,
- old_trust_passwd_hash,
- NULL, &sec_channel_type)) {
+ if (!get_trust_pw_hash(domain, old_trust_passwd_hash, &account_name,
+ &sec_channel_type)) {
DEBUG(0, ("could not fetch domain secrets for domain %s!\n", domain));
return NT_STATUS_UNSUCCESSFUL;
}
-
+
return trust_pw_change_and_store_it(cli, mem_ctx, domain,
+ account_name,
old_trust_passwd_hash,
sec_channel_type);
}