summaryrefslogtreecommitdiff
path: root/source3/lib/netapi/user.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/lib/netapi/user.c')
-rw-r--r--source3/lib/netapi/user.c374
1 files changed, 372 insertions, 2 deletions
diff --git a/source3/lib/netapi/user.c b/source3/lib/netapi/user.c
index f52941235b..6a6cb6c42b 100644
--- a/source3/lib/netapi/user.c
+++ b/source3/lib/netapi/user.c
@@ -1411,10 +1411,380 @@ WERROR NetUserSetInfo_l(struct libnetapi_ctx *ctx,
/****************************************************************
****************************************************************/
+static NTSTATUS query_USER_MODALS_INFO_rpc(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct samr_DomInfo1 *info1,
+ struct samr_DomInfo3 *info3,
+ struct samr_DomInfo5 *info5,
+ struct samr_DomInfo6 *info6,
+ struct samr_DomInfo7 *info7,
+ struct samr_DomInfo12 *info12)
+{
+ NTSTATUS status;
+ union samr_DomainInfo *dom_info = NULL;
+
+ if (info1) {
+ status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
+ domain_handle,
+ 1,
+ &dom_info);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *info1 = dom_info->info1;
+ }
+
+ if (info3) {
+ status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
+ domain_handle,
+ 3,
+ &dom_info);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *info3 = dom_info->info3;
+ }
+
+ if (info5) {
+ status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
+ domain_handle,
+ 5,
+ &dom_info);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *info5 = dom_info->info5;
+ }
+
+ if (info6) {
+ status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
+ domain_handle,
+ 6,
+ &dom_info);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *info6 = dom_info->info6;
+ }
+
+ if (info7) {
+ status = rpccli_samr_QueryDomainInfo(pipe_cli, mem_ctx,
+ domain_handle,
+ 7,
+ &dom_info);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *info7 = dom_info->info7;
+ }
+
+ if (info12) {
+ status = rpccli_samr_QueryDomainInfo2(pipe_cli, mem_ctx,
+ domain_handle,
+ 12,
+ &dom_info);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *info12 = dom_info->info12;
+ }
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS query_USER_MODALS_INFO_0(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_0 *info0)
+{
+ NTSTATUS status;
+ struct samr_DomInfo1 dom_info1;
+ struct samr_DomInfo3 dom_info3;
+
+ ZERO_STRUCTP(info0);
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &dom_info1,
+ &dom_info3,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ info0->usrmod0_min_passwd_len =
+ dom_info1.min_password_length;
+ info0->usrmod0_max_passwd_age =
+ nt_time_to_unix_abs((NTTIME *)&dom_info1.max_password_age);
+ info0->usrmod0_min_passwd_age =
+ nt_time_to_unix_abs((NTTIME *)&dom_info1.min_password_age);
+ info0->usrmod0_password_hist_len =
+ dom_info1.password_history_length;
+
+ info0->usrmod0_force_logoff =
+ nt_time_to_unix_abs(&dom_info3.force_logoff_time);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS query_USER_MODALS_INFO_1(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_1 *info1)
+{
+ NTSTATUS status;
+ struct samr_DomInfo6 dom_info6;
+ struct samr_DomInfo7 dom_info7;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ NULL,
+ NULL,
+ NULL,
+ &dom_info6,
+ &dom_info7,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ info1->usrmod1_primary =
+ talloc_strdup(mem_ctx, dom_info6.primary.string);
+
+ info1->usrmod1_role = dom_info7.role;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS query_USER_MODALS_INFO_2(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct dom_sid *domain_sid,
+ struct USER_MODALS_INFO_2 *info2)
+{
+ NTSTATUS status;
+ struct samr_DomInfo5 dom_info5;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ NULL,
+ NULL,
+ &dom_info5,
+ NULL,
+ NULL,
+ NULL);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ info2->usrmod2_domain_name =
+ talloc_strdup(mem_ctx, dom_info5.domain_name.string);
+ info2->usrmod2_domain_id =
+ (struct domsid *)sid_dup_talloc(mem_ctx, domain_sid);
+
+ NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_name);
+ NT_STATUS_HAVE_NO_MEMORY(info2->usrmod2_domain_id);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS query_USER_MODALS_INFO_3(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ struct policy_handle *domain_handle,
+ struct USER_MODALS_INFO_3 *info3)
+{
+ NTSTATUS status;
+ struct samr_DomInfo12 dom_info12;
+
+ status = query_USER_MODALS_INFO_rpc(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &dom_info12);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ info3->usrmod3_lockout_duration =
+ nt_time_to_unix_abs(&dom_info12.lockout_duration);
+ info3->usrmod3_lockout_observation_window =
+ nt_time_to_unix_abs(&dom_info12.lockout_window);
+ info3->usrmod3_lockout_threshold =
+ dom_info12.lockout_threshold;
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
+static NTSTATUS query_USER_MODALS_INFO_to_buffer(TALLOC_CTX *mem_ctx,
+ struct rpc_pipe_client *pipe_cli,
+ uint32_t level,
+ struct policy_handle *domain_handle,
+ struct dom_sid *domain_sid,
+ uint8_t **buffer)
+{
+ NTSTATUS status;
+
+ struct USER_MODALS_INFO_0 info0;
+ struct USER_MODALS_INFO_1 info1;
+ struct USER_MODALS_INFO_2 info2;
+ struct USER_MODALS_INFO_3 info3;
+
+ if (!buffer) {
+ return ERROR_INSUFFICIENT_BUFFER;
+ }
+
+ switch (level) {
+ case 0:
+ status = query_USER_MODALS_INFO_0(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &info0);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info0,
+ sizeof(info0));
+ break;
+
+ case 1:
+ status = query_USER_MODALS_INFO_1(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &info1);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info1,
+ sizeof(info1));
+ break;
+ case 2:
+ status = query_USER_MODALS_INFO_2(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ domain_sid,
+ &info2);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info2,
+ sizeof(info2));
+ break;
+ case 3:
+ status = query_USER_MODALS_INFO_3(mem_ctx,
+ pipe_cli,
+ domain_handle,
+ &info3);
+ NT_STATUS_NOT_OK_RETURN(status);
+
+ *buffer = (uint8_t *)talloc_memdup(mem_ctx, &info3,
+ sizeof(info3));
+ break;
+ default:
+ break;
+ }
+
+ NT_STATUS_HAVE_NO_MEMORY(*buffer);
+
+ return NT_STATUS_OK;
+}
+
+/****************************************************************
+****************************************************************/
+
WERROR NetUserModalsGet_r(struct libnetapi_ctx *ctx,
struct NetUserModalsGet *r)
{
- return WERR_NOT_SUPPORTED;
+ struct cli_state *cli = NULL;
+ struct rpc_pipe_client *pipe_cli = NULL;
+ NTSTATUS status;
+ WERROR werr;
+
+ struct policy_handle connect_handle, domain_handle;
+ struct dom_sid2 *domain_sid = NULL;
+ uint32_t access_mask = SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT;
+
+ ZERO_STRUCT(connect_handle);
+ ZERO_STRUCT(domain_handle);
+
+ if (!r->out.buffer) {
+ return WERR_INVALID_PARAM;
+ }
+
+ switch (r->in.level) {
+ case 0:
+ access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1 |
+ SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
+ break;
+ case 1:
+ case 2:
+ access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_2;
+ break;
+ case 3:
+ access_mask |= SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1;
+ break;
+ default:
+ werr = WERR_UNKNOWN_LEVEL;
+ goto done;
+ }
+
+ werr = libnetapi_open_ipc_connection(ctx, r->in.server_name, &cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_open_pipe(ctx, cli, &ndr_table_samr.syntax_id,
+ &pipe_cli);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ werr = libnetapi_samr_open_domain(ctx, pipe_cli,
+ SAMR_ACCESS_ENUM_DOMAINS |
+ SAMR_ACCESS_OPEN_DOMAIN,
+ access_mask,
+ &connect_handle,
+ &domain_handle,
+ &domain_sid);
+ if (!W_ERROR_IS_OK(werr)) {
+ goto done;
+ }
+
+ /* 0: 1 + 3 */
+ /* 1: 6 + 7 */
+ /* 2: 5 */
+ /* 3: 12 (DomainInfo2) */
+
+ status = query_USER_MODALS_INFO_to_buffer(ctx,
+ pipe_cli,
+ r->in.level,
+ &domain_handle,
+ domain_sid,
+ r->out.buffer);
+ if (!NT_STATUS_IS_OK(status)) {
+ werr = ntstatus_to_werror(status);
+ goto done;
+ }
+
+ done:
+ if (!cli) {
+ return werr;
+ }
+
+ if (ctx->disable_policy_handle_cache) {
+ libnetapi_samr_close_domain_handle(ctx, &domain_handle);
+ libnetapi_samr_close_connect_handle(ctx, &connect_handle);
+ }
+
+ return werr;
}
/****************************************************************
@@ -1423,7 +1793,7 @@ WERROR NetUserModalsGet_r(struct libnetapi_ctx *ctx,
WERROR NetUserModalsGet_l(struct libnetapi_ctx *ctx,
struct NetUserModalsGet *r)
{
- return WERR_NOT_SUPPORTED;
+ return NetUserModalsGet_r(ctx, r);
}
/****************************************************************