From 89d46eeb33c2d8e2b9b5a06ebe3a369675ae3657 Mon Sep 17 00:00:00 2001 From: Jim McDonough Date: Tue, 30 Jul 2002 17:23:07 +0000 Subject: Add LSA RPC 0x2E, lsa_query_info2. Only level implemented is 0x0c, which is netbios and dns domain info. Also add code to set/fetch the domain GUID from secrets.tdb (although set is not yet called by anyone). (This used to be commit 31d7168530ccce2c5e9e7f96464b47f4d9771a25) --- source3/include/rpc_lsa.h | 38 ++++++++++++++ source3/include/secrets.h | 4 ++ source3/passdb/secrets.c | 32 ++++++++++++ source3/rpc_parse/parse_lsa.c | 110 +++++++++++++++++++++++++++++++++++++++- source3/rpc_server/srv_lsa.c | 37 +++++++++++++- source3/rpc_server/srv_lsa_nt.c | 97 ++++++++++++++++++++++++++++++++++- 6 files changed, 313 insertions(+), 5 deletions(-) diff --git a/source3/include/rpc_lsa.h b/source3/include/rpc_lsa.h index 8e42ac7d2c..39f3e47dc8 100644 --- a/source3/include/rpc_lsa.h +++ b/source3/include/rpc_lsa.h @@ -73,6 +73,7 @@ #define LSA_RETRPRIVDATA 0x2b #define LSA_OPENPOLICY2 0x2c #define LSA_UNK_GET_CONNUSER 0x2d /* LsaGetConnectedCredentials ? */ +#define LSA_QUERYINFO2 0x2e /* XXXX these are here to get a compile! */ #define LSA_LOOKUPRIDS 0xFD @@ -261,6 +262,43 @@ typedef struct lsa_r_query_info } LSA_R_QUERY_INFO; +/* LSA_DNS_DOM_INFO - DNS domain info - info class 12*/ +typedef struct lsa_dns_dom_info +{ + UNIHDR hdr_nb_dom_name; /* netbios domain name */ + UNIHDR hdr_dns_dom_name; + UNIHDR hdr_forest_name; + + GUID dom_guid; /* domain GUID */ + + UNISTR2 uni_nb_dom_name; + UNISTR2 uni_dns_dom_name; + UNISTR2 uni_forest_name; + + uint32 ptr_dom_sid; + DOM_SID2 dom_sid; /* domain SID */ +} LSA_DNS_DOM_INFO; + +typedef union lsa_info2_union +{ + LSA_DNS_DOM_INFO dns_dom_info; +} LSA_INFO2_UNION; + +/* LSA_Q_QUERY_INFO2 - LSA query info */ +typedef struct lsa_q_query_info2 +{ + POLICY_HND pol; /* policy handle */ + uint16 info_class; /* info class */ +} LSA_Q_QUERY_INFO2; + +typedef struct lsa_r_query_info2 +{ + uint32 ptr; /* pointer to info struct */ + uint16 info_class; + LSA_INFO2_UNION info; /* so far the only one */ + NTSTATUS status; +} LSA_R_QUERY_INFO2; + /* LSA_Q_ENUM_TRUST_DOM - LSA enumerate trusted domains */ typedef struct lsa_enum_trust_dom_info { diff --git a/source3/include/secrets.h b/source3/include/secrets.h index 8a5a573bcc..183b29d7a8 100644 --- a/source3/include/secrets.h +++ b/source3/include/secrets.h @@ -35,6 +35,10 @@ #define SECRETS_DOMAIN_SID "SECRETS/SID" #define SECRETS_SAM_SID "SAM/SID" +/* The domain GUID and server GUID (NOT the same) are also not secret */ +#define SECRETS_DOMAIN_GUID "SECRETS/DOMGUID" +#define SECRETS_SERVER_GUID "SECRETS/GUID" + #define SECRETS_LDAP_BIND_PW "SECRETS/LDAP_BIND_PW" /* Authenticated user info is stored in secrets.tdb under these keys */ diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index f967682574..e06452d398 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -128,6 +128,38 @@ BOOL secrets_fetch_domain_sid(char *domain, DOM_SID *sid) return True; } +BOOL secrets_store_domain_guid(char *domain, GUID *guid) +{ + fstring key; + + slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain); + strupper(key); + return secrets_store(key, guid, sizeof(GUID)); +} + +BOOL secrets_fetch_domain_guid(char *domain, GUID *guid) +{ + GUID *dyn_guid; + fstring key; + size_t size; + + slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain); + strupper(key); + dyn_guid = (GUID *)secrets_fetch(key, &size); + + if (dyn_guid == NULL) + return False; + + if (size != sizeof(GUID)) + { + SAFE_FREE(dyn_guid); + return False; + } + + *guid = *dyn_guid; + SAFE_FREE(dyn_guid); + return True; +} /** * Form a key for fetching the machine trust account password diff --git a/source3/rpc_parse/parse_lsa.c b/source3/rpc_parse/parse_lsa.c index a6aecb7967..d0536dab01 100644 --- a/source3/rpc_parse/parse_lsa.c +++ b/source3/rpc_parse/parse_lsa.c @@ -3,8 +3,9 @@ * RPC Pipe client / server routines * Copyright (C) Andrew Tridgell 1992-1997, * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, - * Copyright (C) Paul Ashton 1997. - * Copyright (C) Andrew Bartlett 2002. + * Copyright (C) Paul Ashton 1997, + * Copyright (C) Andrew Bartlett 2002, + * Copyright (C) Jim McDonough 2002. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -2117,3 +2118,108 @@ BOOL policy_handle_is_valid(const POLICY_HND *hnd) ZERO_STRUCT(zero_pol); return ((memcmp(&zero_pol, hnd, sizeof(POLICY_HND)) == 0) ? False : True ); } + +/******************************************************************* + Reads or writes an LSA_DNS_DOM_INFO structure. +********************************************************************/ + +BOOL lsa_io_dns_dom_info(char *desc, LSA_DNS_DOM_INFO *info, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "lsa_io_dns_dom_info"); + depth++; + + if(!prs_align(ps)) + return False; + if(!smb_io_unihdr("nb_name", &info->hdr_nb_dom_name, ps, depth)) + return False; + if(!smb_io_unihdr("dns_name", &info->hdr_dns_dom_name, ps, depth)) + return False; + if(!smb_io_unihdr("forest", &info->hdr_forest_name, ps, depth)) + return False; + + if(!prs_align(ps)) + return False; + if (!prs_uint8s(False, "dom_guid", ps, depth, info->dom_guid.info, GUID_SIZE)) + return False; + + if(!prs_align(ps)) + return False; + if(!prs_uint32("dom_sid", ps, depth, &info->ptr_dom_sid)) + return False; + + if(!smb_io_unistr2("nb_name", &info->uni_nb_dom_name, + info->hdr_nb_dom_name.buffer, ps, depth)) + return False; + if(!smb_io_unistr2("dns_name", &info->uni_dns_dom_name, + info->hdr_dns_dom_name.buffer, ps, depth)) + return False; + if(!smb_io_unistr2("forest", &info->uni_forest_name, + info->hdr_forest_name.buffer, ps, depth)) + return False; + + if(!smb_io_dom_sid2("dom_sid", &info->dom_sid, ps, depth)) + return False; + + return True; + +} + +/******************************************************************* + Reads or writes an LSA_Q_QUERY_DNSDOMINFO structure. +********************************************************************/ + +BOOL lsa_io_q_query_info2(char *desc, LSA_Q_QUERY_INFO2 *q_c, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "lsa_io_q_query_info2"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("pol", &q_c->pol, ps, depth)) + return False; + + if(!prs_uint16("info_class", ps, depth, &q_c->info_class)) + return False; + + return True; +} + +/******************************************************************* + Reads or writes an LSA_R_QUERY_DNSDOMINFO structure. +********************************************************************/ + +BOOL lsa_io_r_query_info2(char *desc, LSA_R_QUERY_INFO2 *r_c, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "lsa_io_r_query_info2"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("ptr", ps, depth, &r_c->ptr)) + return False; + if(!prs_uint16("info_class", ps, depth, &r_c->info_class)) + return False; + switch(r_c->info_class) { + case 0x000c: + if (!lsa_io_dns_dom_info("info12", &r_c->info.dns_dom_info, + ps, depth)) + return False; + break; + default: + DEBUG(0,("lsa_io_r_query_info2: unknown info class %d\n", + r_c->info_class)); + return False; + } + + if(!prs_align(ps)) + return False; + if(!prs_ntstatus("status", ps, depth, &r_c->status)) + return False; + + return True; +} diff --git a/source3/rpc_server/srv_lsa.c b/source3/rpc_server/srv_lsa.c index e5a4d3b46d..e3495576c9 100644 --- a/source3/rpc_server/srv_lsa.c +++ b/source3/rpc_server/srv_lsa.c @@ -3,8 +3,9 @@ * RPC Pipe client / server routines * Copyright (C) Andrew Tridgell 1992-1997, * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, - * Copyright (C) Paul Ashton 1997. - * Copyright (C) Jeremy Allison 2001. + * Copyright (C) Paul Ashton 1997, + * Copyright (C) Jeremy Allison 2001, + * Copyright (C) Jim McDonough 2002. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -609,6 +610,37 @@ static BOOL api_lsa_query_secobj(pipes_struct *p) return True; } +/*************************************************************************** + api_lsa_query_dnsdomainfo + ***************************************************************************/ + +static BOOL api_lsa_query_info2(pipes_struct *p) +{ + LSA_Q_QUERY_INFO2 q_u; + LSA_R_QUERY_INFO2 r_u; + + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!lsa_io_q_query_info2("", &q_u, data, 0)) { + DEBUG(0,("api_lsa_query_info2: failed to unmarshall LSA_Q_QUERY_INFO2.\n")); + return False; + } + + r_u.status = _lsa_query_info2(p, &q_u, &r_u); + + if (!lsa_io_r_query_info2("", &r_u, rdata, 0)) { + DEBUG(0,("api_lsa_query_info2: failed to marshall LSA_R_QUERY_INFO2.\n")); + return False; + } + + return True; +} + + /*************************************************************************** \PIPE\ntlsa commands ***************************************************************************/ @@ -634,6 +666,7 @@ static struct api_struct api_lsa_cmds[] = { "LSA_ADDPRIVS" , LSA_ADDPRIVS , api_lsa_addprivs }, { "LSA_REMOVEPRIVS" , LSA_REMOVEPRIVS , api_lsa_removeprivs }, { "LSA_QUERYSECOBJ" , LSA_QUERYSECOBJ , api_lsa_query_secobj }, + { "LSA_QUERYINFO2" , LSA_QUERYINFO2 , api_lsa_query_info2 }, { NULL , 0 , NULL } }; diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index d072061a5f..f28441886a 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -5,7 +5,8 @@ * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, * Copyright (C) Paul Ashton 1997, * Copyright (C) Jeremy Allison 2001, - * Copyright (C) Rafal Szczesniak 2002. + * Copyright (C) Rafal Szczesniak 2002, + * Copyright (C) Jim McDonough 2002. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -341,6 +342,48 @@ static NTSTATUS lsa_get_generic_sd(TALLOC_CTX *mem_ctx, SEC_DESC **sd, size_t *s return NT_STATUS_OK; } +/*************************************************************************** + init_dns_dom_info. + ***************************************************************************/ +static void init_dns_dom_info(LSA_DNS_DOM_INFO *r_l, char *nb_name, + char *dns_name, char *forest_name, + GUID *dom_guid, DOM_SID *dom_sid) +{ + if (nb_name && *nb_name) { + init_uni_hdr(&r_l->hdr_nb_dom_name, strlen(nb_name)); + init_unistr2(&r_l->uni_nb_dom_name, nb_name, + strlen(nb_name)); + r_l->hdr_nb_dom_name.uni_max_len += 2; + r_l->uni_nb_dom_name.uni_max_len += 1; + } + + if (dns_name && *dns_name) { + init_uni_hdr(&r_l->hdr_dns_dom_name, strlen(dns_name)); + init_unistr2(&r_l->uni_dns_dom_name, dns_name, + strlen(dns_name)); + r_l->hdr_dns_dom_name.uni_max_len += 2; + r_l->uni_dns_dom_name.uni_max_len += 1; + } + + if (forest_name && *forest_name) { + init_uni_hdr(&r_l->hdr_forest_name, strlen(forest_name)); + init_unistr2(&r_l->uni_forest_name, forest_name, + strlen(forest_name)); + r_l->hdr_forest_name.uni_max_len += 2; + r_l->uni_forest_name.uni_max_len += 1; + } + + /* how do we init the guid ? probably should write an init fn */ + if (dom_guid) { + memcpy(&r_l->dom_guid, dom_guid, sizeof(GUID)); + } + + if (dom_sid) { + r_l->ptr_dom_sid = 1; + init_dom_sid2(&r_l->dom_sid, dom_sid); + } +} + /*************************************************************************** _lsa_open_policy2. ***************************************************************************/ @@ -1166,3 +1209,55 @@ NTSTATUS _lsa_query_secobj(pipes_struct *p, LSA_Q_QUERY_SEC_OBJ *q_u, LSA_R_QUER } +NTSTATUS _lsa_query_info2(pipes_struct *p, LSA_Q_QUERY_INFO2 *q_u, LSA_R_QUERY_INFO2 *r_u) +{ + struct lsa_info *handle; + char *nb_name = NULL; + char *dns_name = NULL; + char *forest_name = NULL; + DOM_SID *sid = NULL; + GUID guid; + + ZERO_STRUCT(guid); + r_u->status = NT_STATUS_OK; + + if (!find_policy_by_hnd(p, &q_u->pol, (void **)&handle)) + return NT_STATUS_INVALID_HANDLE; + + switch (q_u->info_class) { + case 0x0c: + /* check if the user have enough rights */ + if (!(handle->access & POLICY_VIEW_LOCAL_INFORMATION)) + return NT_STATUS_ACCESS_DENIED; + + /* Request PolicyPrimaryDomainInformation. */ + switch (lp_server_role()) { + case ROLE_DOMAIN_PDC: + case ROLE_DOMAIN_BDC: + nb_name = global_myworkgroup; + /* ugly temp hack for these next two */ + dns_name = lp_realm(); + forest_name = lp_realm(); + sid = get_global_sam_sid(); + secrets_fetch_domain_guid(global_myworkgroup, + &guid); + break; + default: + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + init_dns_dom_info(&r_u->info.dns_dom_info, nb_name, dns_name, + forest_name,&guid,sid); + break; + default: + DEBUG(0,("_lsa_query_info2: unknown info level in Lsa Query: %d\n", q_u->info_class)); + r_u->status = NT_STATUS_INVALID_INFO_CLASS; + break; + } + + if (NT_STATUS_IS_OK(r_u->status)) { + r_u->ptr = 0x1; + r_u->info_class = q_u->info_class; + } + + return r_u->status; +} -- cgit