From 4bc39f05b77a8601506fa144a20d7e9ab9c3efe6 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 8 Jun 2005 13:59:03 +0000 Subject: r7391: - Added client-support for various lsa_query_trust_dom_info-calls and a rpcclient-tester for some info-levels. Jerry, I tried to adopt to prs_pointer() where possible and to not interfere with your work for usrmgr. - Add "net rpc trustdom vampire"-tool. This allows to retrieve Interdomain Trust(ed)-Relationships from NT4-Servers including cleartext-passwords (still stored in the local secrets.tdb). The net-hook was done in cooperation with Lars Mueller . To vampire trusted domains simply call: net rpc trustdom vampire -S nt4dc -Uadmin%pass Guenther (This used to be commit 512585293963a1737f831af697ea1dc092d63cb0) --- source3/include/rpc_lsa.h | 156 +++++++++++++++++- source3/libsmb/smbencrypt.c | 66 ++++++++ source3/rpc_client/cli_lsarpc.c | 195 ++++++++++++++++++++++ source3/rpc_parse/parse_lsa.c | 346 +++++++++++++++++++++++++++++++++++++++- source3/rpcclient/cmd_lsarpc.c | 188 ++++++++++++++++++++++ source3/rpcclient/rpcclient.c | 4 +- source3/utils/net_rpc.c | 209 ++++++++++++++++++++++-- 7 files changed, 1146 insertions(+), 18 deletions(-) (limited to 'source3') diff --git a/source3/include/rpc_lsa.h b/source3/include/rpc_lsa.h index fe444bfdd1..053a23b218 100644 --- a/source3/include/rpc_lsa.h +++ b/source3/include/rpc_lsa.h @@ -60,7 +60,7 @@ #define LSA_GETSYSTEMACCOUNT 0x17 #define LSA_SETSYSTEMACCOUNT 0x18 #define LSA_OPENTRUSTDOM 0x19 /* TODO: implement this one -- jerry */ -#define LSA_QUERYTRUSTDOM 0x1a +#define LSA_QUERYTRUSTDOMINFO 0x1a #define LSA_SETINFOTRUSTDOM 0x1b #define LSA_OPENSECRET 0x1c /* TODO: implement this one -- jerry */ #define LSA_SETSECRET 0x1d /* TODO: implement this one -- jerry */ @@ -73,7 +73,7 @@ #define LSA_ENUMACCTRIGHTS 0x24 #define LSA_ADDACCTRIGHTS 0x25 #define LSA_REMOVEACCTRIGHTS 0x26 -#define LSA_QUERYTRUSTDOMINFO 0x27 +#define LSA_QUERYTRUSTDOMINFOBYSID 0x27 #define LSA_SETTRUSTDOMINFO 0x28 #define LSA_DELETETRUSTDOM 0x29 #define LSA_STOREPRIVDATA 0x2a @@ -81,6 +81,8 @@ #define LSA_OPENPOLICY2 0x2c #define LSA_UNK_GET_CONNUSER 0x2d /* LsaGetConnectedCredentials ? */ #define LSA_QUERYINFO2 0x2e +#define LSA_QUERYTRUSTDOMINFOBYNAME 0x30 +#define LSA_OPENTRUSTDOMBYNAME 0x37 /* XXXX these are here to get a compile! */ #define LSA_LOOKUPRIDS 0xFD @@ -724,16 +726,27 @@ typedef struct lsa_r_removeprivs } LSA_R_REMOVEPRIVS; /*******************************************************/ - +#if 0 /* jerry, I think this not correct - gd */ typedef struct { POLICY_HND handle; uint32 count; /* ??? this is what ethereal calls it */ DOM_SID sid; } LSA_Q_OPEN_TRUSTED_DOMAIN; +#endif +/* LSA_Q_OPEN_TRUSTED_DOMAIN - LSA Query Open Trusted Domain */ +typedef struct lsa_q_open_trusted_domain +{ + POLICY_HND pol; /* policy handle */ + DOM_SID2 sid; /* domain sid */ + uint32 access_mask; /* access mask */ + +} LSA_Q_OPEN_TRUSTED_DOMAIN; + +/* LSA_R_OPEN_TRUSTED_DOMAIN - response to LSA Query Open Trusted Domain */ typedef struct { - POLICY_HND handle; - NTSTATUS status; + POLICY_HND handle; /* trustdom policy handle */ + NTSTATUS status; /* return code */ } LSA_R_OPEN_TRUSTED_DOMAIN; @@ -810,5 +823,138 @@ typedef struct { NTSTATUS status; } LSA_R_SET_SECRET; +/* LSA_Q_QUERY_TRUSTED_DOMAIN_INFO - LSA query trusted domain info */ +typedef struct lsa_query_trusted_domain_info +{ + POLICY_HND pol; /* policy handle */ + uint16 info_class; /* info class */ + +} LSA_Q_QUERY_TRUSTED_DOMAIN_INFO; + +/* LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_SID - LSA query trusted domain info */ +typedef struct lsa_query_trusted_domain_info_by_sid +{ + POLICY_HND pol; /* policy handle */ + DOM_SID2 dom_sid; /* domain sid */ + uint16 info_class; /* info class */ + +} LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_SID; + +/* LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_NAME - LSA query trusted domain info */ +typedef struct lsa_query_trusted_domain_info_by_name +{ + POLICY_HND pol; /* policy handle */ + LSA_STRING domain_name; /* domain name */ + uint16 info_class; /* info class */ + +} LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_NAME; + +typedef struct trusted_domain_info_name { + LSA_STRING netbios_name; +} TRUSTED_DOMAIN_INFO_NAME; + +typedef struct trusted_domain_info_posix_offset { + uint32 posix_offset; +} TRUSTED_DOMAIN_INFO_POSIX_OFFSET; + +typedef struct lsa_data_buf { + uint32 size; + uint32 offset; + uint32 length; + uint8 *data; +} LSA_DATA_BUF; + +typedef struct lsa_data_buf_hdr { + uint32 length; + uint32 size; + uint32 data_ptr; +} LSA_DATA_BUF_HDR; + + +typedef struct lsa_data_buf2 { + uint32 size; + uint8 *data; +} LSA_DATA_BUF2; + +typedef struct trusted_domain_info_password { + uint32 ptr_password; + uint32 ptr_old_password; + LSA_DATA_BUF_HDR password_hdr; + LSA_DATA_BUF_HDR old_password_hdr; + LSA_DATA_BUF password; + LSA_DATA_BUF old_password; +} TRUSTED_DOMAIN_INFO_PASSWORD; + +typedef struct trusted_domain_info_basic { + LSA_STRING netbios_name; + DOM_SID2 sid; +} TRUSTED_DOMAIN_INFO_BASIC; + +typedef struct trusted_domain_info_ex { + LSA_STRING domain_name; + LSA_STRING netbios_name; + DOM_SID2 sid; + uint32 trust_direction; + uint32 trust_type; + uint32 trust_attributes; +} TRUSTED_DOMAIN_INFO_EX; + +typedef struct trust_domain_info_buffer { + NTTIME last_update_time; + uint32 secret_type; + LSA_DATA_BUF2 data; +} LSA_TRUSTED_DOMAIN_INFO_BUFFER; + +typedef struct trusted_domain_info_auth_info { + uint32 incoming_count; + LSA_TRUSTED_DOMAIN_INFO_BUFFER incoming_current_auth_info; + LSA_TRUSTED_DOMAIN_INFO_BUFFER incoming_previous_auth_info; + uint32 outgoing_count; + LSA_TRUSTED_DOMAIN_INFO_BUFFER outgoing_current_auth_info; + LSA_TRUSTED_DOMAIN_INFO_BUFFER outgoing_previous_auth_info; +} TRUSTED_DOMAIN_INFO_AUTH_INFO; + +typedef struct trusted_domain_info_full_info { + TRUSTED_DOMAIN_INFO_EX info_ex; + TRUSTED_DOMAIN_INFO_POSIX_OFFSET posix_offset; + TRUSTED_DOMAIN_INFO_AUTH_INFO auth_info; +} TRUSTED_DOMAIN_INFO_FULL_INFO; + +typedef struct trusted_domain_info_11 { + TRUSTED_DOMAIN_INFO_EX info_ex; + LSA_DATA_BUF2 data1; +} TRUSTED_DOMAIN_INFO_11; + +typedef struct trusted_domain_info_all { + TRUSTED_DOMAIN_INFO_EX info_ex; + LSA_DATA_BUF2 data1; + TRUSTED_DOMAIN_INFO_POSIX_OFFSET posix_offset; + TRUSTED_DOMAIN_INFO_AUTH_INFO auth_info; +} TRUSTED_DOMAIN_INFO_ALL; + +/* LSA_TRUSTED_DOMAIN_INFO */ +typedef union lsa_trusted_domain_info +{ + uint16 info_class; + TRUSTED_DOMAIN_INFO_NAME name; + /* deprecated - gd + TRUSTED_DOMAIN_INFO_CONTROLLERS_INFO controllers; */ + TRUSTED_DOMAIN_INFO_POSIX_OFFSET posix_offset; + TRUSTED_DOMAIN_INFO_PASSWORD password; + TRUSTED_DOMAIN_INFO_BASIC basic; + TRUSTED_DOMAIN_INFO_EX info_ex; + TRUSTED_DOMAIN_INFO_AUTH_INFO auth_info; + TRUSTED_DOMAIN_INFO_FULL_INFO full_info; + TRUSTED_DOMAIN_INFO_11 info11; + TRUSTED_DOMAIN_INFO_ALL info_all; + +} LSA_TRUSTED_DOMAIN_INFO; + +/* LSA_R_QUERY_TRUSTED_DOMAIN_INFO - LSA query trusted domain info */ +typedef struct r_lsa_query_trusted_domain_info +{ + LSA_TRUSTED_DOMAIN_INFO *info; + NTSTATUS status; +} LSA_R_QUERY_TRUSTED_DOMAIN_INFO; #endif /* _RPC_LSA_H */ diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c index ab61f6b419..8361c35a8e 100644 --- a/source3/libsmb/smbencrypt.c +++ b/source3/libsmb/smbencrypt.c @@ -583,3 +583,69 @@ void sess_crypt_blob(DATA_BLOB *out, const DATA_BLOB *in, const DATA_BLOB *sessi memcpy(&out->data[i], bout, MIN(8, in->length-i)); } } + +/* Decrypts password-blob with session-key + * @param pass password for session-key + * @param data_in DATA_BLOB encrypted password + * + * Returns cleartext password in CH_UNIX + * Caller must free the returned string + */ + +char *decrypt_trustdom_secret(const char *pass, DATA_BLOB *data_in) +{ + DATA_BLOB data_out, sess_key; + uchar nt_hash[16]; + uint32_t length; + uint32_t version; + fstring cleartextpwd; + + if (!data_in || !pass) + return NULL; + + /* generate md4 password-hash derived from the NT UNICODE password */ + E_md4hash(pass, nt_hash); + + /* hashed twice with md4 */ + mdfour(nt_hash, nt_hash, 16); + + /* 16-Byte session-key */ + sess_key = data_blob(nt_hash, 16); + if (sess_key.data == NULL) + return NULL; + + data_out = data_blob(NULL, data_in->length); + if (data_out.data == NULL) + return NULL; + + /* decrypt with des3 */ + sess_crypt_blob(&data_out, data_in, &sess_key, 0); + + /* 4 Byte length, 4 Byte version */ + length = IVAL(data_out.data, 0); + version = IVAL(data_out.data, 4); + + if (length > data_in->length - 8) { + DEBUG(0,("decrypt_trustdom_secret: invalid length (%d)\n", length)); + return NULL; + } + + if (version != 1) { + DEBUG(0,("decrypt_trustdom_secret: unknown version number (%d)\n", version)); + return NULL; + } + + rpcstr_pull(cleartextpwd, data_out.data + 8, sizeof(fstring), length, 0 ); + +#ifdef DEBUG_PASSWORD + DEBUG(100,("decrypt_trustdom_secret: length is: %d, version is: %d, password is: %s\n", + length, version, cleartextpwd)); +#endif + + data_blob_free(&data_out); + data_blob_free(&sess_key); + + return SMB_STRDUP(cleartextpwd); + +} + diff --git a/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c index f404b5144a..47dd0b1ea3 100644 --- a/source3/rpc_client/cli_lsarpc.c +++ b/source3/rpc_client/cli_lsarpc.c @@ -1452,4 +1452,199 @@ Error was : %s.\n", remote_machine, cli_errstr(&cli) )); #endif +NTSTATUS cli_lsa_open_trusted_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol, DOM_SID *dom_sid, uint32 access_mask, + POLICY_HND *trustdom_pol) +{ + prs_struct qbuf, rbuf; + LSA_Q_OPEN_TRUSTED_DOMAIN q; + LSA_R_OPEN_TRUSTED_DOMAIN r; + NTSTATUS result; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Initialise input parameters */ + + init_lsa_q_open_trusted_domain(&q, pol, dom_sid, access_mask); + + /* Marshall data and send request */ + + if (!lsa_io_q_open_trusted_domain("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, PI_LSARPC, LSA_OPENTRUSTDOM, &qbuf, &rbuf)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* Unmarshall response */ + + if (!lsa_io_r_open_trusted_domain("", &r, &rbuf, 0)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* Return output parameters */ + + if (NT_STATUS_IS_OK(result = r.status)) { + *trustdom_pol = r.handle; + } + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +NTSTATUS cli_lsa_query_trusted_domain_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol, + uint16 info_class, DOM_SID *dom_sid, + LSA_TRUSTED_DOMAIN_INFO **info) +{ + prs_struct qbuf, rbuf; + LSA_Q_QUERY_TRUSTED_DOMAIN_INFO q; + LSA_R_QUERY_TRUSTED_DOMAIN_INFO r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_q_query_trusted_domain_info(&q, pol, info_class); + + if (!lsa_io_q_query_trusted_domain_info("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, PI_LSARPC, LSA_QUERYTRUSTDOMINFO, &qbuf, &rbuf)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* Unmarshall response */ + + if (!lsa_io_r_query_trusted_domain_info("", &r, &rbuf, 0)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + if (!NT_STATUS_IS_OK(result = r.status)) { + goto done; + } + + *info = r.info; + +done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + + +NTSTATUS cli_lsa_query_trusted_domain_info_by_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol, + uint16 info_class, DOM_SID *dom_sid, + LSA_TRUSTED_DOMAIN_INFO **info) +{ + prs_struct qbuf, rbuf; + LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_SID q; + LSA_R_QUERY_TRUSTED_DOMAIN_INFO r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_q_query_trusted_domain_info_by_sid(&q, pol, info_class, dom_sid); + + if (!lsa_io_q_query_trusted_domain_info_by_sid("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, PI_LSARPC, LSA_QUERYTRUSTDOMINFOBYSID, &qbuf, &rbuf)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* Unmarshall response */ + + if (!lsa_io_r_query_trusted_domain_info("", &r, &rbuf, 0)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + if (!NT_STATUS_IS_OK(result = r.status)) { + goto done; + } + + *info = r.info; + +done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + +NTSTATUS cli_lsa_query_trusted_domain_info_by_name(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *pol, + uint16 info_class, const char *domain_name, + LSA_TRUSTED_DOMAIN_INFO **info) +{ + prs_struct qbuf, rbuf; + LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_NAME q; + LSA_R_QUERY_TRUSTED_DOMAIN_INFO r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_q_query_trusted_domain_info_by_name(&q, pol, info_class, domain_name); + + if (!lsa_io_q_query_trusted_domain_info_by_name("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, PI_LSARPC, LSA_QUERYTRUSTDOMINFOBYNAME, &qbuf, &rbuf)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* Unmarshall response */ + + if (!lsa_io_r_query_trusted_domain_info("", &r, &rbuf, 0)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + if (!NT_STATUS_IS_OK(result = r.status)) { + goto done; + } + + *info = r.info; + +done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + /** @} **/ + diff --git a/source3/rpc_parse/parse_lsa.c b/source3/rpc_parse/parse_lsa.c index 6d0a0bfc51..884012c9be 100644 --- a/source3/rpc_parse/parse_lsa.c +++ b/source3/rpc_parse/parse_lsa.c @@ -2503,8 +2503,21 @@ BOOL lsa_io_r_remove_acct_rights(const char *desc, LSA_R_REMOVE_ACCT_RIGHTS *out } /******************************************************************* + Inits an LSA_Q_OPEN_TRUSTED_DOMAIN structure. ********************************************************************/ +void init_lsa_q_open_trusted_domain(LSA_Q_OPEN_TRUSTED_DOMAIN *q, POLICY_HND *hnd, DOM_SID *sid, uint32 desired_access) +{ + memcpy(&q->pol, hnd, sizeof(q->pol)); + + init_dom_sid2(&q->sid, sid); + q->access_mask = desired_access; +} + +/******************************************************************* +********************************************************************/ + +#if 0 /* jerry, I think this not correct - gd */ BOOL lsa_io_q_open_trusted_domain(const char *desc, LSA_Q_OPEN_TRUSTED_DOMAIN *in, prs_struct *ps, int depth) { prs_debug(ps, depth, desc, "lsa_io_q_open_trusted_domain"); @@ -2524,8 +2537,34 @@ BOOL lsa_io_q_open_trusted_domain(const char *desc, LSA_Q_OPEN_TRUSTED_DOMAIN *i return True; } +#endif + +/******************************************************************* + Reads or writes an LSA_Q_OPEN_TRUSTED_DOMAIN structure. +********************************************************************/ + +BOOL lsa_io_q_open_trusted_domain(const char *desc, LSA_Q_OPEN_TRUSTED_DOMAIN *q_o, prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "lsa_io_q_open_trusted_domain"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("pol", &q_o->pol, ps, depth)) + return False; + + if(!smb_io_dom_sid2("sid", &q_o->sid, ps, depth)) + return False; + + if(!prs_uint32("access", ps, depth, &q_o->access_mask)) + return False; + + return True; +} /******************************************************************* + Reads or writes an LSA_R_OPEN_TRUSTED_DOMAIN structure. ********************************************************************/ BOOL lsa_io_r_open_trusted_domain(const char *desc, LSA_R_OPEN_TRUSTED_DOMAIN *out, prs_struct *ps, int depth) @@ -2536,7 +2575,7 @@ BOOL lsa_io_r_open_trusted_domain(const char *desc, LSA_R_OPEN_TRUSTED_DOMAIN *o if(!prs_align(ps)) return False; - if (!smb_io_pol_hnd("", &out->handle, ps, depth)) + if (!smb_io_pol_hnd("handle", &out->handle, ps, depth)) return False; if(!prs_ntstatus("status", ps, depth, &out->status)) @@ -2726,3 +2765,308 @@ BOOL lsa_io_r_delete_object(const char *desc, LSA_R_DELETE_OBJECT *out, prs_stru return True; } + +/******************************************************************* + Inits an LSA_Q_QUERY_TRUSTED_DOMAIN_INFO structure. +********************************************************************/ + +void init_q_query_trusted_domain_info(LSA_Q_QUERY_TRUSTED_DOMAIN_INFO *q, + POLICY_HND *hnd, uint16 info_class) +{ + DEBUG(5, ("init_q_query_trusted_domain_info\n")); + + q->pol = *hnd; + q->info_class = info_class; +} + +/******************************************************************* + Inits an LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_NAME structure. +********************************************************************/ + +void init_q_query_trusted_domain_info_by_name(LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_NAME *q, + POLICY_HND *hnd, uint16 info_class, + const char *dom_name) +{ + DEBUG(5, ("init_q_query_trusted_domain_info_by_name\n")); + + q->pol = *hnd; + init_lsa_string(&q->domain_name, dom_name ); + q->info_class = info_class; +} + +/******************************************************************* + Inits an LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_SID structure. +********************************************************************/ + +void init_q_query_trusted_domain_info_by_sid(LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_SID *q, + POLICY_HND *hnd, uint16 info_class, + DOM_SID *dom_sid) +{ + DEBUG(5, ("init_q_query_trusted_domain_info_by_sid\n")); + + q->pol = *hnd; + init_dom_sid2(&q->dom_sid, dom_sid); + q->info_class = info_class; +} + +/******************************************************************* + Reads or writes an LSA_Q_QUERY_TRUSTED_DOMAIN_INFO structure. +********************************************************************/ + +BOOL lsa_io_q_query_trusted_domain_info(const char *desc, + LSA_Q_QUERY_TRUSTED_DOMAIN_INFO *q_q, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "lsa_io_q_query_trusted_domain_info"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("pol", &q_q->pol, ps, depth)) + return False; + + if(!prs_uint16("info_class", ps, depth, &q_q->info_class)) + return False; + + return True; +} + + +/******************************************************************* + Reads or writes an LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_SID structure. +********************************************************************/ + +BOOL lsa_io_q_query_trusted_domain_info_by_sid(const char *desc, + LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_SID *q_q, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "lsa_io_q_query_trusted_domain_info_by_sid"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("pol", &q_q->pol, ps, depth)) + return False; + + if(!prs_align(ps)) + return False; + + if(!smb_io_dom_sid2("dom_sid", &q_q->dom_sid, ps, depth)) + return False; + + if(!prs_uint16("info_class", ps, depth, &q_q->info_class)) + return False; + + return True; +} + +/******************************************************************* + Reads or writes an LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_NAME structure. +********************************************************************/ + +BOOL lsa_io_q_query_trusted_domain_info_by_name(const char *desc, + LSA_Q_QUERY_TRUSTED_DOMAIN_INFO_BY_NAME *q_q, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "lsa_io_q_query_trusted_domain_info_by_name"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("pol", &q_q->pol, ps, depth)) + return False; + + if(!prs_align(ps)) + return False; + + if(!smb_io_lsa_string("domain_name", &q_q->domain_name, ps, depth)) + return False; + + if(!prs_uint16("info_class", ps, depth, &q_q->info_class)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +static BOOL smb_io_lsa_data_buf_hdr(const char *desc, LSA_DATA_BUF_HDR *buf_hdr, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "smb_io_lsa_data_buf_hdr"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("length", ps, depth, &buf_hdr->length)) + return False; + + if(!prs_uint32("size", ps, depth, &buf_hdr->size)) + return False; + + if (!prs_uint32("data_ptr", ps, depth, &buf_hdr->data_ptr)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +static BOOL smb_io_lsa_data_buf(const char *desc, LSA_DATA_BUF *buf, + prs_struct *ps, int depth, int length, int size) +{ + prs_debug(ps, depth, desc, "smb_io_lsa_data_buf"); + depth++; + + if ( UNMARSHALLING(ps) ) { + if ( !(buf->data = PRS_ALLOC_MEM( ps, uint8, length )) ) + return False; + } + + if (!prs_uint32("size", ps, depth, &buf->size)) + return False; + + if (!prs_uint32("offset", ps, depth, &buf->offset)) + return False; + + if (!prs_uint32("length", ps, depth, &buf->length)) + return False; + + if(!prs_uint8s(False, "data", ps, depth, buf->data, size)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +static BOOL lsa_io_trustdom_query_1(const char *desc, TRUSTED_DOMAIN_INFO_NAME *name, + prs_struct *ps, int depth) +{ + if (!smb_io_lsa_string("netbios_name", &name->netbios_name, ps, depth)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +static BOOL lsa_io_trustdom_query_3(const char *desc, TRUSTED_DOMAIN_INFO_POSIX_OFFSET *posix, + prs_struct *ps, int depth) +{ + if(!prs_uint32("posix_offset", ps, depth, &posix->posix_offset)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +static BOOL lsa_io_trustdom_query_4(const char *desc, TRUSTED_DOMAIN_INFO_PASSWORD *password, + prs_struct *ps, int depth) +{ + if(!prs_align(ps)) + return False; + + if(!prs_uint32("ptr_password", ps, depth, &password->ptr_password)) + return False; + + if(!prs_uint32("ptr_old_password", ps, depth, &password->ptr_old_password)) + return False; + + if (&password->ptr_password) { + + if (!smb_io_lsa_data_buf_hdr("password_hdr", &password->password_hdr, ps, depth)) + return False; + + if (!smb_io_lsa_data_buf("password", &password->password, ps, depth, + password->password_hdr.length, password->password_hdr.size)) + return False; + } + + if (&password->ptr_old_password) { + + if (!smb_io_lsa_data_buf_hdr("old_password_hdr", &password->old_password_hdr, ps, depth)) + return False; + + if (!smb_io_lsa_data_buf("old_password", &password->old_password, ps, depth, + password->old_password_hdr.length, password->old_password_hdr.size)) + return False; + } + + return True; +} + +/******************************************************************* +********************************************************************/ + +static BOOL lsa_io_trustdom_query(const char *desc, prs_struct *ps, int depth, LSA_TRUSTED_DOMAIN_INFO *info) +{ + prs_debug(ps, depth, desc, "lsa_io_trustdom_query"); + depth++; + + if(!prs_uint16("info_class", ps, depth, &info->info_class)) + return False; + + if(!prs_align(ps)) + return False; + + switch (info->info_class) { + case 1: + if(!lsa_io_trustdom_query_1("name", &info->name, ps, depth)) + return False; + break; + case 3: + if(!lsa_io_trustdom_query_3("posix_offset", &info->posix_offset, ps, depth)) + return False; + break; + case 4: + if(!lsa_io_trustdom_query_4("password", &info->password, ps, depth)) + return False; + break; + default: + DEBUG(0,("unsupported info-level: %d\n", info->info_class)); + return False; + break; + } + + return True; +} + +/******************************************************************* + Reads or writes an LSA_R_QUERY_TRUSTED_DOMAIN_INFO structure. +********************************************************************/ + +BOOL lsa_io_r_query_trusted_domain_info(const char *desc, + LSA_R_QUERY_TRUSTED_DOMAIN_INFO *r_q, + prs_struct *ps, int depth) +{ + if (r_q == NULL) + return False; + + prs_debug(ps, depth, desc, "lsa_io_r_query_trusted_domain_info"); + depth++; + + if (!prs_pointer("trustdom", ps, depth, (void**)&r_q->info, + sizeof(LSA_TRUSTED_DOMAIN_INFO), + (PRS_POINTER_CAST)lsa_io_trustdom_query) ) + return False; + + if(!prs_align(ps)) + return False; + + if(!prs_ntstatus("status", ps, depth, &r_q->status)) + return False; + + return True; +} + diff --git a/source3/rpcclient/cmd_lsarpc.c b/source3/rpcclient/cmd_lsarpc.c index f6ecd8c706..cccf9679e3 100644 --- a/source3/rpcclient/cmd_lsarpc.c +++ b/source3/rpcclient/cmd_lsarpc.c @@ -746,6 +746,191 @@ static NTSTATUS cmd_lsa_query_secobj(struct cli_state *cli, return result; } +static void display_trust_dom_info_1(TRUSTED_DOMAIN_INFO_NAME *n) +{ + printf("NetBIOS Name:\t%s\n", unistr2_static(&n->netbios_name.unistring)); +} + +static void display_trust_dom_info_3(TRUSTED_DOMAIN_INFO_POSIX_OFFSET *p) +{ + printf("Posix Offset:\t%d\n", p->posix_offset); +} + +static void display_trust_dom_info_4(TRUSTED_DOMAIN_INFO_PASSWORD *p, const char *password) +{ + char *pwd, *pwd_old; + + DATA_BLOB data = data_blob(NULL, p->password.length); + DATA_BLOB data_old = data_blob(NULL, p->old_password.length); + + memcpy(data.data, p->password.data, p->password.length); + data.length = p->password.length; + + memcpy(data_old.data, p->old_password.data, p->old_password.length); + data_old.length = p->old_password.length; + + pwd = decrypt_trustdom_secret(password, &data); + pwd_old = decrypt_trustdom_secret(password, &data_old); + + printf("Password:\t%s\n", pwd); + printf("Old Password:\t%s\n", pwd_old); + + SAFE_FREE(pwd); + SAFE_FREE(pwd_old); + + data_blob_free(&data); + data_blob_free(&data_old); +} + +static void display_trust_dom_info(LSA_TRUSTED_DOMAIN_INFO *info, uint32 info_class, const char *pass) +{ + switch (info_class) { + case 1: + display_trust_dom_info_1(&info->name); + break; + case 3: + display_trust_dom_info_3(&info->posix_offset); + break; + case 4: + display_trust_dom_info_4(&info->password, pass); + break; + default: + printf("unsupported info-class: %d\n", info_class); + break; + } +} + +static NTSTATUS cmd_lsa_query_trustdominfobysid(struct cli_state *cli, + TALLOC_CTX *mem_ctx, int argc, + const char **argv) +{ + POLICY_HND pol; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DOM_SID dom_sid; + uint32 access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED; + LSA_TRUSTED_DOMAIN_INFO *info; + + uint32 info_class = 1; + + if (argc > 3 || argc < 2) { + printf("Usage: %s [sid] [info_class]\n", argv[0]); + return NT_STATUS_OK; + } + + if (!string_to_sid(&dom_sid, argv[1])) + return NT_STATUS_NO_MEMORY; + + if (argc == 3) + info_class = atoi(argv[2]); + + result = cli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + result = cli_lsa_query_trusted_domain_info_by_sid(cli, mem_ctx, &pol, + info_class, &dom_sid, &info); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + display_trust_dom_info(info, info_class, cli->pwd.password); + + done: + if (&pol) + cli_lsa_close(cli, mem_ctx, &pol); + + return result; +} + +static NTSTATUS cmd_lsa_query_trustdominfobyname(struct cli_state *cli, + TALLOC_CTX *mem_ctx, int argc, + const char **argv) +{ + POLICY_HND pol; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + uint32 access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED; + LSA_TRUSTED_DOMAIN_INFO *info; + uint32 info_class = 1; + + if (argc > 3 || argc < 2) { + printf("Usage: %s [name] [info_class]\n", argv[0]); + return NT_STATUS_OK; + } + + if (argc == 3) + info_class = atoi(argv[2]); + + result = cli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + result = cli_lsa_query_trusted_domain_info_by_name(cli, mem_ctx, &pol, + info_class, argv[1], &info); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + display_trust_dom_info(info, info_class, cli->pwd.password); + + done: + if (&pol) + cli_lsa_close(cli, mem_ctx, &pol); + + return result; +} + +static NTSTATUS cmd_lsa_query_trustdominfo(struct cli_state *cli, + TALLOC_CTX *mem_ctx, int argc, + const char **argv) +{ + POLICY_HND pol, trustdom_pol; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + uint32 access_mask = SEC_RIGHTS_MAXIMUM_ALLOWED; + LSA_TRUSTED_DOMAIN_INFO *info; + DOM_SID dom_sid; + uint32 info_class = 1; + + if (argc > 3 || argc < 2) { + printf("Usage: %s [sid] [info_class]\n", argv[0]); + return NT_STATUS_OK; + } + + if (!string_to_sid(&dom_sid, argv[1])) + return NT_STATUS_NO_MEMORY; + + + if (argc == 3) + info_class = atoi(argv[2]); + + result = cli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + result = cli_lsa_open_trusted_domain(cli, mem_ctx, &pol, + &dom_sid, access_mask, &trustdom_pol); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + result = cli_lsa_query_trusted_domain_info(cli, mem_ctx, &trustdom_pol, + info_class, &dom_sid, &info); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + display_trust_dom_info(info, info_class, cli->pwd.password); + + done: + if (&pol) + cli_lsa_close(cli, mem_ctx, &pol); + + return result; +} + + /* List of commands exported by this module */ @@ -771,6 +956,9 @@ struct cmd_set lsarpc_commands[] = { { "lsaremoveacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_remove_acct_rights, NULL, PI_LSARPC, "Remove rights from an account", "" }, { "lsalookupprivvalue", RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_priv_value, NULL, PI_LSARPC, "Get a privilege value given its name", "" }, { "lsaquerysecobj", RPC_RTYPE_NTSTATUS, cmd_lsa_query_secobj, NULL, PI_LSARPC, "Query LSA security object", "" }, + { "lsaquerytrustdominfo",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfo, NULL, PI_LSARPC, "Query LSA trusted domains info (given a SID)", "" }, + { "lsaquerytrustdominfobyname",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfobyname, NULL, PI_LSARPC, "Query LSA trusted domains info (given a name), only works for Windows > 2k", "" }, + { "lsaquerytrustdominfobysid",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfobysid, NULL, PI_LSARPC, "Query LSA trusted domains info (given a SID)", "" }, { NULL } }; diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index c02a279db9..14004327ad 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -204,10 +204,10 @@ static NTSTATUS cmd_listcommands(struct cli_state *cli, TALLOC_CTX *mem_ctx, i = 0; tmp_set++; while(tmp_set->name) { - printf("%20s", tmp_set->name); + printf("%30s", tmp_set->name); tmp_set++; i++; - if (i%4 == 0) + if (i%3 == 0) printf("\n"); } diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 3956756489..9793932b51 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -4795,6 +4795,7 @@ static int rpc_trustdom_usage(int argc, const char **argv) d_printf(" net rpc trustdom establish \t establish relationship to trusted domain\n"); d_printf(" net rpc trustdom revoke \t abandon relationship to trusted domain\n"); d_printf(" net rpc trustdom list \t show current interdomain trust relationships\n"); + d_printf(" net rpc trustdom vampire \t vampire interdomain trust relationships from remote server\n"); return -1; } @@ -4810,6 +4811,201 @@ static NTSTATUS rpc_query_domain_sid(const DOM_SID *domain_sid, return NT_STATUS_OK; } +static void print_trusted_domain(DOM_SID *dom_sid, const char *trusted_dom_name) +{ + fstring ascii_sid, padding; + int pad_len, col_len = 20; + + /* convert sid into ascii string */ + sid_to_string(ascii_sid, dom_sid); + + /* calculate padding space for d_printf to look nicer */ + pad_len = col_len - strlen(trusted_dom_name); + padding[pad_len] = 0; + do padding[--pad_len] = ' '; while (pad_len); + + d_printf("%s%s%s\n", trusted_dom_name, padding, ascii_sid); +} + +static NTSTATUS vampire_trusted_domain(struct cli_state *cli, + TALLOC_CTX *mem_ctx, + POLICY_HND *pol, + DOM_SID dom_sid, + const char *trusted_dom_name) +{ + NTSTATUS nt_status; + LSA_TRUSTED_DOMAIN_INFO *info; + char *cleartextpwd; + DATA_BLOB data; + smb_ucs2_t *uni_dom_name; + + nt_status = cli_lsa_query_trusted_domain_info_by_sid(cli, mem_ctx, pol, 4, &dom_sid, &info); + + if (NT_STATUS_IS_ERR(nt_status)) { + DEBUG(0,("Could not query trusted domain info. Error was %s\n", + nt_errstr(nt_status))); + goto done; + } + + data = data_blob(NULL, info->password.password.length); + + memcpy(data.data, info->password.password.data, info->password.password.length); + data.length = info->password.password.length; + + cleartextpwd = decrypt_trustdom_secret(cli->pwd.password, &data); + + if (cleartextpwd == NULL) { + DEBUG(0,("retrieved NULL password\n")); + nt_status = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + if (push_ucs2_talloc(mem_ctx, &uni_dom_name, trusted_dom_name) < 0) { + DEBUG(0, ("Could not convert domain name %s to unicode\n", + trusted_dom_name)); + nt_status = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + if (!secrets_store_trusted_domain_password(trusted_dom_name, + uni_dom_name, + strlen_w(uni_dom_name)+1, + cleartextpwd, + dom_sid)) { + DEBUG(0, ("Storing password for trusted domain failed.\n")); + nt_status = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + DEBUG(100,("sucessfully vampired trusted domain [%s], sid: [%s], password: [%s]\n", + trusted_dom_name, sid_string_static(&dom_sid), cleartextpwd)); + +done: + SAFE_FREE(cleartextpwd); + data_blob_free(&data); + + return nt_status; +} + +static int rpc_trustdom_vampire(int argc, const char **argv) +{ + /* common variables */ + TALLOC_CTX* mem_ctx; + struct cli_state *cli; + NTSTATUS nt_status; + const char *domain_name = NULL; + DOM_SID *queried_dom_sid; + POLICY_HND connect_hnd; + + /* trusted domains listing variables */ + unsigned int num_domains, enum_ctx = 0; + int i; + DOM_SID *domain_sids; + char **trusted_dom_names; + fstring pdc_name; + char *dummy; + + /* + * Listing trusted domains (stored in secrets.tdb, if local) + */ + + mem_ctx = talloc_init("trust relationships vampire"); + + /* + * set domain and pdc name to local samba server (default) + * or to remote one given in command line + */ + + if (StrCaseCmp(opt_workgroup, lp_workgroup())) { + domain_name = opt_workgroup; + opt_target_workgroup = opt_workgroup; + } else { + fstrcpy(pdc_name, global_myname()); + domain_name = talloc_strdup(mem_ctx, lp_workgroup()); + opt_target_workgroup = domain_name; + }; + + /* open \PIPE\lsarpc and open policy handle */ + if (!(cli = net_make_ipc_connection(NET_FLAGS_PDC))) { + DEBUG(0, ("Couldn't connect to domain controller\n")); + return -1; + }; + + if (!cli_nt_session_open(cli, PI_LSARPC)) { + DEBUG(0, ("Could not initialise lsa pipe\n")); + return -1; + }; + + nt_status = cli_lsa_open_policy2(cli, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE, + &connect_hnd); + if (NT_STATUS_IS_ERR(nt_status)) { + DEBUG(0, ("Couldn't open policy handle. Error was %s\n", + nt_errstr(nt_status))); + return -1; + }; + + /* query info level 5 to obtain sid of a domain being queried */ + nt_status = cli_lsa_query_info_policy( + cli, mem_ctx, &connect_hnd, 5 /* info level */, + &dummy, &queried_dom_sid); + + if (NT_STATUS_IS_ERR(nt_status)) { + DEBUG(0, ("LSA Query Info failed. Returned error was %s\n", + nt_errstr(nt_status))); + return -1; + } + + /* + * Keep calling LsaEnumTrustdom over opened pipe until + * the end of enumeration is reached + */ + + d_printf("Vampire trusted domains:\n\n"); + + do { + nt_status = cli_lsa_enum_trust_dom(cli, mem_ctx, &connect_hnd, &enum_ctx, + &num_domains, + &trusted_dom_names, &domain_sids); + + if (NT_STATUS_IS_ERR(nt_status)) { + DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n", + nt_errstr(nt_status))); + return -1; + }; + + for (i = 0; i < num_domains; i++) { + + print_trusted_domain(&(domain_sids[i]), trusted_dom_names[i]); + + nt_status = vampire_trusted_domain(cli, mem_ctx, &connect_hnd, + domain_sids[i], trusted_dom_names[i]); + if (!NT_STATUS_IS_OK(nt_status)) + return -1; + }; + + /* + * in case of no trusted domains say something rather + * than just display blank line + */ + if (!num_domains) d_printf("none\n"); + + } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES)); + + /* close this connection before doing next one */ + nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd); + if (NT_STATUS_IS_ERR(nt_status)) { + DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n", + nt_errstr(nt_status))); + return -1; + }; + + /* close lsarpc pipe and connection to IPC$ */ + cli_nt_session_close(cli); + cli_shutdown(cli); + + talloc_destroy(mem_ctx); + return 0; +} static int rpc_trustdom_list(int argc, const char **argv) { @@ -4819,7 +5015,7 @@ static int rpc_trustdom_list(int argc, const char **argv) NTSTATUS nt_status; const char *domain_name = NULL; DOM_SID *queried_dom_sid; - fstring ascii_sid, padding; + fstring padding; int ascii_dom_name_len; POLICY_HND connect_hnd; @@ -4905,15 +5101,7 @@ static int rpc_trustdom_list(int argc, const char **argv) }; for (i = 0; i < num_domains; i++) { - /* convert sid into ascii string */ - sid_to_string(ascii_sid, &(domain_sids[i])); - - /* calculate padding space for d_printf to look nicer */ - pad_len = col_len - strlen(trusted_dom_names[i]); - padding[pad_len] = 0; - do padding[--pad_len] = ' '; while (pad_len); - - d_printf("%s%s%s\n", trusted_dom_names[i], padding, ascii_sid); + print_trusted_domain(&(domain_sids[i]), trusted_dom_names[i]); }; /* @@ -5065,6 +5253,7 @@ static int rpc_trustdom(int argc, const char **argv) {"revoke", rpc_trustdom_revoke}, {"help", rpc_trustdom_usage}, {"list", rpc_trustdom_list}, + {"vampire", rpc_trustdom_vampire}, {NULL, NULL} }; -- cgit