diff options
Diffstat (limited to 'source3/libsmb')
-rw-r--r-- | source3/libsmb/clifile.c | 144 | ||||
-rw-r--r-- | source3/libsmb/clikrb5.c | 9 | ||||
-rw-r--r-- | source3/libsmb/clispnego.c | 35 | ||||
-rw-r--r-- | source3/libsmb/dsgetdcname.c | 2 | ||||
-rw-r--r-- | source3/libsmb/trusts_util.c | 58 |
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, + ¶ms, &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); } |