static NTSTATUS cmd_samr_create_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, char **argv) { POLICY_HND connect_pol, domain_pol, user_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; char *acct_name; uint16 acb_info; uint32 unknown, user_rid; if (argc != 2) { printf("Usage: %s username\n", argv[0]); return NT_STATUS_OK; } acct_name = argv[1]; /* Get sam policy handle */ result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } /* Get domain policy handle */ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } /* Create domain user */ acb_info = ACB_NORMAL; unknown = 0xe005000b; /* No idea what this is - a permission mask? */ result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol, acct_name, acb_info, unknown, &user_pol, &user_rid); if (!NT_STATUS_IS_OK(result)) { goto done; } done: return result; }
static NTSTATUS cmd_samr_enum_dom_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, char **argv) { POLICY_HND connect_pol, domain_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 start_idx, size, num_dom_groups, i; struct acct_info *dom_groups; if (argc != 1) { printf("Usage: %s\n", argv[0]); return NT_STATUS_OK; } /* Get sam policy handle */ result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } /* Get domain policy handle */ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } /* Enumerate domain groups */ start_idx = 0; size = 0xffff; result = cli_samr_enum_dom_groups(cli, mem_ctx, &domain_pol, &start_idx, size, &dom_groups, &num_dom_groups); for (i = 0; i < num_dom_groups; i++) printf("group:[%s] rid:[0x%x]\n", dom_groups[i].acct_name, dom_groups[i].rid); done: return result; }
static PyObject *samr_open_domain(PyObject *self, PyObject *args, PyObject *kw) { samr_connect_hnd_object *connect_hnd = (samr_connect_hnd_object *)self; static char *kwlist[] = { "sid", "access", NULL }; uint32 desired_access = MAXIMUM_ALLOWED_ACCESS; char *sid_str; DOM_SID sid; TALLOC_CTX *mem_ctx = NULL; POLICY_HND domain_pol; NTSTATUS ntstatus; PyObject *result = NULL; if (!PyArg_ParseTupleAndKeywords( args, kw, "s|i", kwlist, &sid_str, &desired_access)) return NULL; if (!string_to_sid(&sid, sid_str)) { PyErr_SetString(PyExc_TypeError, "string is not a sid"); return NULL; } if (!(mem_ctx = talloc_init("samr_open_domain"))) { PyErr_SetString(samr_error, "unable to init talloc context"); return NULL; } ntstatus = cli_samr_open_domain( connect_hnd->cli, mem_ctx, &connect_hnd->connect_pol, desired_access, &sid, &domain_pol); if (!NT_STATUS_IS_OK(ntstatus)) { PyErr_SetObject(samr_ntstatus, py_ntstatus_tuple(ntstatus)); goto done; } result = new_samr_domain_hnd_object( connect_hnd->cli, mem_ctx, &domain_pol); done: if (!result) { if (mem_ctx) talloc_destroy(mem_ctx); } return result; }
static NTSTATUS cmd_samr_lookup_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { POLICY_HND connect_pol, domain_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 access_mask = MAXIMUM_ALLOWED_ACCESS; fstring domain_name,sid_string; DOM_SID sid; if (argc != 2) { printf("Usage: %s domain_name\n", argv[0]); return NT_STATUS_OK; } sscanf(argv[1], "%s", domain_name); result = try_samr_connects(cli, mem_ctx, access_mask, &connect_pol); if (!NT_STATUS_IS_OK(result)) goto done; result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, access_mask, &domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) goto done; result = cli_samr_lookup_domain( cli, mem_ctx, &connect_pol, domain_name, &sid); sid_to_string(sid_string,&sid); if (NT_STATUS_IS_OK(result)) printf("SAMR_LOOKUP_DOMAIN: Domain Name: %s Domain SID: %s\n", domain_name,sid_string); done: return result; }
/* list all domain groups */ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, uint32 *num_entries, struct acct_info **info) { uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; CLI_POLICY_HND *hnd; POLICY_HND dom_pol; NTSTATUS status; uint32 start = 0; int retry; NTSTATUS result; *num_entries = 0; *info = NULL; DEBUG(3,("rpc: enum_dom_groups\n")); retry = 0; do { if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd))) return result; status = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, des_access, &domain->sid, &dom_pol); } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); if (!NT_STATUS_IS_OK(status)) return status; do { struct acct_info *info2 = NULL; uint32 count = 0; TALLOC_CTX *mem_ctx2; mem_ctx2 = talloc_init("enum_dom_groups[rpc]"); /* start is updated by this call. */ status = cli_samr_enum_dom_groups(hnd->cli, mem_ctx2, &dom_pol, &start, 0xFFFF, /* buffer size? */ &info2, &count); if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { talloc_destroy(mem_ctx2); break; } (*info) = talloc_realloc(mem_ctx, *info, sizeof(**info) * ((*num_entries) + count)); if (! *info) { talloc_destroy(mem_ctx2); cli_samr_close(hnd->cli, mem_ctx, &dom_pol); return NT_STATUS_NO_MEMORY; } memcpy(&(*info)[*num_entries], info2, count*sizeof(*info2)); (*num_entries) += count; talloc_destroy(mem_ctx2); } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)); cli_samr_close(hnd->cli, mem_ctx, &dom_pol); return status; }
/* Query display info for a domain. This returns enough information plus a bit extra to give an overview of domain users for the User Manager application. */ static NTSTATUS query_user_list(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, uint32 *num_entries, WINBIND_USERINFO **info) { CLI_POLICY_HND *hnd; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; POLICY_HND dom_pol; BOOL got_dom_pol = False; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; unsigned int i, start_idx, retry; uint32 loop_count; DEBUG(3,("rpc: query_user_list\n")); *num_entries = 0; *info = NULL; retry = 0; do { /* Get sam handle */ if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)) ) return result; /* Get domain handle */ result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, des_access, &domain->sid, &dom_pol); } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); if (!NT_STATUS_IS_OK(result)) goto done; got_dom_pol = True; i = start_idx = 0; loop_count = 0; do { TALLOC_CTX *ctx2; uint32 num_dom_users, j; uint32 max_entries, max_size; SAM_DISPINFO_CTR ctr; SAM_DISPINFO_1 info1; ZERO_STRUCT( ctr ); ZERO_STRUCT( info1 ); ctr.sam.info1 = &info1; if (!(ctx2 = talloc_init("winbindd enum_users"))) { result = NT_STATUS_NO_MEMORY; goto done; } /* this next bit is copied from net_user_list_internal() */ get_query_dispinfo_params( loop_count, &max_entries, &max_size ); result = cli_samr_query_dispinfo(hnd->cli, mem_ctx, &dom_pol, &start_idx, 1, &num_dom_users, max_entries, max_size, &ctr); loop_count++; *num_entries += num_dom_users; *info = talloc_realloc( mem_ctx, *info, (*num_entries) * sizeof(WINBIND_USERINFO)); if (!(*info)) { result = NT_STATUS_NO_MEMORY; talloc_destroy(ctx2); goto done; } for (j = 0; j < num_dom_users; i++, j++) { fstring username, fullname; uint32 rid = ctr.sam.info1->sam[j].rid_user; unistr2_to_ascii( username, &(&ctr.sam.info1->str[j])->uni_acct_name, sizeof(username)-1); unistr2_to_ascii( fullname, &(&ctr.sam.info1->str[j])->uni_full_name, sizeof(fullname)-1); (*info)[i].acct_name = talloc_strdup(mem_ctx, username ); (*info)[i].full_name = talloc_strdup(mem_ctx, fullname ); (*info)[i].user_sid = rid_to_talloced_sid(domain, mem_ctx, rid ); /* For the moment we set the primary group for every user to be the Domain Users group. There are serious problems with determining the actual primary group for large domains. This should really be made into a 'winbind force group' smb.conf parameter or something like that. */ (*info)[i].group_sid = rid_to_talloced_sid(domain, mem_ctx, DOMAIN_GROUP_RID_USERS); } talloc_destroy(ctx2); } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); done: if (got_dom_pol) cli_samr_close(hnd->cli, mem_ctx, &dom_pol); return result; }
static NTSTATUS cmd_samr_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, char **argv) { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; POLICY_HND connect_pol, domain_pol; uint32 flags = 0x000003e8; /* Unknown */ uint32 num_rids, num_names, *name_types, *rids; const char **names; int i; DOM_SID global_sid_Builtin; string_to_sid(&global_sid_Builtin, "S-1-5-32"); if (argc < 3) { printf("Usage: %s domain|builtin name1 [name2 [name3] [...]]\n", argv[0]); printf("check on the domain SID: S-1-5-21-x-y-z\n"); printf("or check on the builtin SID: S-1-5-32\n"); return NT_STATUS_OK; } /* Get sam policy and domain handles */ result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } if (StrCaseCmp(argv[1], "domain")==0) result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); else if (StrCaseCmp(argv[1], "builtin")==0) result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &global_sid_Builtin, &domain_pol); else return NT_STATUS_OK; if (!NT_STATUS_IS_OK(result)) { goto done; } /* Look up names */ num_names = argc - 2; names = (const char **)talloc(mem_ctx, sizeof(char *) * num_names); for (i = 0; i < argc - 2; i++) names[i] = argv[i + 2]; result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, flags, num_names, names, &num_rids, &rids, &name_types); if (!NT_STATUS_IS_OK(result)) { goto done; } /* Display results */ for (i = 0; i < num_names; i++) printf("name %s: 0x%x (%d)\n", names[i], rids[i], name_types[i]); done: return result; }
int net_rpc_join_newstyle(int argc, const char **argv) { /* libsmb variables */ struct cli_state *cli; TALLOC_CTX *mem_ctx; uint32 acb_info = ACB_WSTRUST; uint32 sec_channel_type; /* rpc variables */ POLICY_HND lsa_pol, sam_pol, domain_pol, user_pol; DOM_SID *domain_sid; uint32 user_rid; /* Password stuff */ char *clear_trust_password = NULL; uchar pwbuf[516]; SAM_USERINFO_CTR ctr; SAM_USER_INFO_24 p24; SAM_USER_INFO_10 p10; uchar md4_trust_password[16]; /* Misc */ NTSTATUS result; int retval = 1; char *domain; uint32 num_rids, *name_types, *user_rids; uint32 flags = 0x3e8; char *acct_name; const char *const_acct_name; /* check what type of join */ if (argc >= 0) { sec_channel_type = get_sec_channel_type(argv[0]); } else { sec_channel_type = get_sec_channel_type(NULL); } switch (sec_channel_type) { case SEC_CHAN_WKSTA: acb_info = ACB_WSTRUST; break; case SEC_CHAN_BDC: acb_info = ACB_SVRTRUST; break; #if 0 case SEC_CHAN_DOMAIN: acb_info = ACB_DOMTRUST; break; #endif } /* Connect to remote machine */ if (!(cli = net_make_ipc_connection(NET_FLAGS_PDC))) return 1; if (!(mem_ctx = talloc_init("net_rpc_join_newstyle"))) { DEBUG(0, ("Could not initialise talloc context\n")); goto done; } /* Fetch domain sid */ if (!cli_nt_session_open(cli, PI_LSARPC)) { DEBUG(0, ("Error connecting to LSA pipe\n")); goto done; } CHECK_RPC_ERR(cli_lsa_open_policy(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol), "error opening lsa policy handle"); CHECK_RPC_ERR(cli_lsa_query_info_policy(cli, mem_ctx, &lsa_pol, 5, &domain, &domain_sid), "error querying info policy"); cli_lsa_close(cli, mem_ctx, &lsa_pol); cli_nt_session_close(cli); /* Done with this pipe */ /* Create domain user */ if (!cli_nt_session_open(cli, PI_SAMR)) { DEBUG(0, ("Error connecting to SAM pipe\n")); goto done; } CHECK_RPC_ERR(cli_samr_connect(cli, mem_ctx, SEC_RIGHTS_MAXIMUM_ALLOWED, &sam_pol), "could not connect to SAM database"); CHECK_RPC_ERR(cli_samr_open_domain(cli, mem_ctx, &sam_pol, SEC_RIGHTS_MAXIMUM_ALLOWED, domain_sid, &domain_pol), "could not open domain"); /* Create domain user */ acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname()); strlower_m(acct_name); const_acct_name = acct_name; result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol, acct_name, acb_info, 0xe005000b, &user_pol, &user_rid); if (!NT_STATUS_IS_OK(result) && !NT_STATUS_EQUAL(result, NT_STATUS_USER_EXISTS)) { d_printf("Creation of workstation account failed\n"); /* If NT_STATUS_ACCESS_DENIED then we have a valid username/password combo but the user does not have administrator access. */ if (NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) d_printf("User specified does not have administrator privileges\n"); goto done; } /* We *must* do this.... don't ask... */ if (NT_STATUS_IS_OK(result)) cli_samr_close(cli, mem_ctx, &user_pol); CHECK_RPC_ERR_DEBUG(cli_samr_lookup_names(cli, mem_ctx, &domain_pol, flags, 1, &const_acct_name, &num_rids, &user_rids, &name_types), ("error looking up rid for user %s: %s\n", acct_name, nt_errstr(result))); if (name_types[0] != SID_NAME_USER) { DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types[0])); goto done; } user_rid = user_rids[0]; /* Open handle on user */ CHECK_RPC_ERR_DEBUG( cli_samr_open_user(cli, mem_ctx, &domain_pol, SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol), ("could not re-open existing user %s: %s\n", acct_name, nt_errstr(result))); /* Create a random machine account password */ { char *str; str = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH); clear_trust_password = SMB_STRDUP(str); E_md4hash(clear_trust_password, md4_trust_password); } encode_pw_buffer(pwbuf, clear_trust_password, STR_UNICODE); /* Set password on machine account */ ZERO_STRUCT(ctr); ZERO_STRUCT(p24); init_sam_user_info24(&p24, (char *)pwbuf,24); ctr.switch_value = 24; ctr.info.id24 = &p24; CHECK_RPC_ERR(cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 24, &cli->user_session_key, &ctr), "error setting trust account password"); /* Why do we have to try to (re-)set the ACB to be the same as what we passed in the samr_create_dom_user() call? When a NT workstation is joined to a domain by an administrator the acb_info is set to 0x80. For a normal user with "Add workstations to the domain" rights the acb_info is 0x84. I'm not sure whether it is supposed to make a difference or not. NT seems to cope with either value so don't bomb out if the set userinfo2 level 0x10 fails. -tpot */ ZERO_STRUCT(ctr); ctr.switch_value = 0x10; ctr.info.id10 = &p10; init_sam_user_info10(&p10, acb_info); /* Ignoring the return value is necessary for joining a domain as a normal user with "Add workstation to domain" privilege. */ result = cli_samr_set_userinfo2(cli, mem_ctx, &user_pol, 0x10, &cli->user_session_key, &ctr); /* Now check the whole process from top-to-bottom */ cli_samr_close(cli, mem_ctx, &user_pol); cli_nt_session_close(cli); /* Done with this pipe */ if (!cli_nt_session_open(cli, PI_NETLOGON)) { DEBUG(0,("Error connecting to NETLOGON pipe\n")); goto done; } /* ensure that schannel uses the right domain */ fstrcpy(cli->domain, domain); result = cli_nt_establish_netlogon(cli, sec_channel_type, md4_trust_password); if (!NT_STATUS_IS_OK(result)) { DEBUG(0, ("Error domain join verification (reused connection): %s\n\n", nt_errstr(result))); if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && (sec_channel_type == SEC_CHAN_BDC) ) { d_printf("Please make sure that no computer account\n" "named like this machine (%s) exists in the domain\n", global_myname()); } goto done; } /* Now store the secret in the secrets database */ strupper_m(domain); if (!secrets_store_domain_sid(domain, domain_sid)) { DEBUG(0, ("error storing domain sid for %s\n", domain)); goto done; } if (!secrets_store_machine_password(clear_trust_password, domain, sec_channel_type)) { DEBUG(0, ("error storing plaintext domain secrets for %s\n", domain)); } /* double-check, connection from scratch */ retval = net_rpc_join_ok(domain); done: /* Close down pipe - this will clean up open policy handles */ if (cli->nt_pipe_fnum[cli->pipe_idx]) cli_nt_session_close(cli); /* Display success or failure */ if (retval != 0) { fprintf(stderr,"Unable to join domain %s.\n",domain); } else { printf("Joined domain %s.\n",domain); } cli_shutdown(cli); SAFE_FREE(clear_trust_password); return retval; }
static NTSTATUS cmd_samr_query_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { POLICY_HND connect_pol, domain_pol, alias_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 alias_rid, num_members, i; uint32 access_mask = MAXIMUM_ALLOWED_ACCESS; DOM_SID *alias_sids; DOM_SID global_sid_Builtin; string_to_sid(&global_sid_Builtin, "S-1-5-32"); if ((argc < 3) || (argc > 4)) { printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]); return NT_STATUS_OK; } sscanf(argv[2], "%i", &alias_rid); if (argc > 3) sscanf(argv[3], "%x", &access_mask); /* Open SAMR handle */ result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) goto done; /* Open handle on domain */ if (StrCaseCmp(argv[1], "domain")==0) result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); else if (StrCaseCmp(argv[1], "builtin")==0) result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &global_sid_Builtin, &domain_pol); else return NT_STATUS_OK; if (!NT_STATUS_IS_OK(result)) goto done; /* Open handle on alias */ result = cli_samr_open_alias(cli, mem_ctx, &domain_pol, access_mask, alias_rid, &alias_pol); if (!NT_STATUS_IS_OK(result)) goto done; result = cli_samr_query_aliasmem(cli, mem_ctx, &alias_pol, &num_members, &alias_sids); if (!NT_STATUS_IS_OK(result)) goto done; for (i = 0; i < num_members; i++) { fstring sid_str; sid_to_string(sid_str, &alias_sids[i]); printf("\tsid:[%s]\n", sid_str); } done: return result; }
static NTSTATUS cmd_samr_query_usergroups(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { POLICY_HND connect_pol, domain_pol, user_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 num_groups, user_rid; uint32 access_mask = MAXIMUM_ALLOWED_ACCESS; DOM_GID *user_gids; int i; fstring server; if ((argc < 2) || (argc > 3)) { printf("Usage: %s rid [access mask]\n", argv[0]); return NT_STATUS_OK; } sscanf(argv[1], "%i", &user_rid); if (argc > 2) sscanf(argv[2], "%x", &access_mask); slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); strupper_m(server); result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) goto done; result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) goto done; result = cli_samr_open_user(cli, mem_ctx, &domain_pol, access_mask, user_rid, &user_pol); if (!NT_STATUS_IS_OK(result)) goto done; result = cli_samr_query_usergroups(cli, mem_ctx, &user_pol, &num_groups, &user_gids); if (!NT_STATUS_IS_OK(result)) goto done; for (i = 0; i < num_groups; i++) { printf("\tgroup rid:[0x%x] attr:[0x%x]\n", user_gids[i].g_rid, user_gids[i].attr); } done: return result; }
/********************************************************************** * Query user information */ static NTSTATUS cmd_samr_query_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { POLICY_HND connect_pol, domain_pol, user_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 info_level = 21; uint32 access_mask = MAXIMUM_ALLOWED_ACCESS; SAM_USERINFO_CTR *user_ctr; fstring server; uint32 user_rid; if ((argc < 2) || (argc > 4)) { printf("Usage: %s rid [info level] [access mask] \n", argv[0]); return NT_STATUS_OK; } sscanf(argv[1], "%i", &user_rid); if (argc > 2) sscanf(argv[2], "%i", &info_level); if (argc > 3) sscanf(argv[3], "%x", &access_mask); slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); strupper_m(server); result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) goto done; result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) goto done; result = cli_samr_open_user(cli, mem_ctx, &domain_pol, access_mask, user_rid, &user_pol); if (!NT_STATUS_IS_OK(result)) goto done; ZERO_STRUCT(user_ctr); result = cli_samr_query_userinfo(cli, mem_ctx, &user_pol, info_level, &user_ctr); if (!NT_STATUS_IS_OK(result)) goto done; display_sam_user_info_21(user_ctr->info.id21); done: return result; }
/* Lookup group membership given a rid. */ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const DOM_SID *group_sid, uint32 *num_names, DOM_SID ***sid_mem, char ***names, uint32 **name_types) { CLI_POLICY_HND *hnd = NULL; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 i, total_names = 0; POLICY_HND dom_pol, group_pol; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; BOOL got_dom_pol = False, got_group_pol = False; uint32 *rid_mem = NULL; uint32 group_rid; int retry; unsigned int j; fstring sid_string; DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name, sid_to_string(sid_string, group_sid))); if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid)) { goto done; } *num_names = 0; retry = 0; do { /* Get sam handle */ if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd))) goto done; /* Get domain handle */ result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, des_access, &domain->sid, &dom_pol); } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); if (!NT_STATUS_IS_OK(result)) goto done; got_dom_pol = True; /* Get group handle */ result = cli_samr_open_group(hnd->cli, mem_ctx, &dom_pol, des_access, group_rid, &group_pol); if (!NT_STATUS_IS_OK(result)) goto done; got_group_pol = True; /* Step #1: Get a list of user rids that are the members of the group. */ result = cli_samr_query_groupmem(hnd->cli, mem_ctx, &group_pol, num_names, &rid_mem, name_types); if (!NT_STATUS_IS_OK(result)) goto done; if (!*num_names) { names = NULL; name_types = NULL; sid_mem = NULL; goto done; } /* Step #2: Convert list of rids into list of usernames. Do this in bunches of ~1000 to avoid crashing NT4. It looks like there is a buffer overflow or something like that lurking around somewhere. */ #define MAX_LOOKUP_RIDS 900 *names = talloc_zero(mem_ctx, *num_names * sizeof(char *)); *name_types = talloc_zero(mem_ctx, *num_names * sizeof(uint32)); *sid_mem = talloc_zero(mem_ctx, *num_names * sizeof(DOM_SID *)); for (j=0;j<(*num_names);j++) { (*sid_mem)[j] = rid_to_talloced_sid(domain, mem_ctx, (rid_mem)[j]); } if (*num_names>0 && (!*names || !*name_types)) { result = NT_STATUS_NO_MEMORY; goto done; } for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) { int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS); uint32 tmp_num_names = 0; char **tmp_names = NULL; uint32 *tmp_types = NULL; /* Lookup a chunk of rids */ result = cli_samr_lookup_rids(hnd->cli, mem_ctx, &dom_pol, 1000, /* flags */ num_lookup_rids, &rid_mem[i], &tmp_num_names, &tmp_names, &tmp_types); /* see if we have a real error (and yes the STATUS_SOME_UNMAPPED is the one returned from 2k) */ if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) != NT_STATUS_V(STATUS_SOME_UNMAPPED)) goto done; /* Copy result into array. The talloc system will take care of freeing the temporary arrays later on. */ memcpy(&(*names)[i], tmp_names, sizeof(char *) * tmp_num_names); memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) * tmp_num_names); total_names += tmp_num_names; } *num_names = total_names; result = NT_STATUS_OK; done: if (got_group_pol) cli_samr_close(hnd->cli, mem_ctx, &group_pol); if (got_dom_pol) cli_samr_close(hnd->cli, mem_ctx, &dom_pol); return result; }
/********************************************************************** * Query user security object */ static NTSTATUS cmd_samr_query_sec_obj(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, char **argv) { POLICY_HND connect_pol, domain_pol, user_pol, *pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 info_level = 4; fstring server; uint32 user_rid = 0; TALLOC_CTX *ctx = NULL; SEC_DESC_BUF *sec_desc_buf=NULL; BOOL domain = False; ctx=talloc_init(); if (argc > 2) { printf("Usage: %s [rid|-d]\n", argv[0]); printf("\tSpecify rid for security on user, -d for security on domain\n"); return NT_STATUS_OK; } if (argc == 2) { if (strcmp(argv[1], "-d") == 0) domain = True; else sscanf(argv[1], "%i", &user_rid); } slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); strupper (server); result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) goto done; if (domain || user_rid) result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) goto done; if (user_rid) result = cli_samr_open_user(cli, mem_ctx, &domain_pol, MAXIMUM_ALLOWED_ACCESS, user_rid, &user_pol); if (!NT_STATUS_IS_OK(result)) goto done; /* Pick which query pol to use */ pol = &connect_pol; if (domain) pol = &domain_pol; if (user_rid) pol = &user_pol; /* Query SAM security object */ result = cli_samr_query_sec_obj(cli, mem_ctx, pol, info_level, ctx, &sec_desc_buf); if (!NT_STATUS_IS_OK(result)) goto done; display_sec_desc(sec_desc_buf->sec); done: talloc_destroy(ctx); return result; }
static NTSTATUS cmd_samr_query_useraliases(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, char **argv) { POLICY_HND connect_pol, domain_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 user_rid, num_aliases, *alias_rids; int i; fstring server; DOM_SID tmp_sid; DOM_SID2 sid; DOM_SID global_sid_Builtin; string_to_sid(&global_sid_Builtin, "S-1-5-32"); if (argc != 3) { printf("Usage: %s builtin|domain rid\n", argv[0]); return NT_STATUS_OK; } sscanf(argv[2], "%i", &user_rid); slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); strupper (server); result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } if (StrCaseCmp(argv[1], "domain")==0) result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); else if (StrCaseCmp(argv[1], "builtin")==0) result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &global_sid_Builtin, &domain_pol); else return NT_STATUS_OK; if (!NT_STATUS_IS_OK(result)) { goto done; } sid_copy(&tmp_sid, &domain_sid); sid_append_rid(&tmp_sid, user_rid); init_dom_sid2(&sid, &tmp_sid); result = cli_samr_query_useraliases(cli, mem_ctx, &domain_pol, 1, &sid, &num_aliases, &alias_rids); if (!NT_STATUS_IS_OK(result)) { goto done; } for (i = 0; i < num_aliases; i++) { printf("\tgroup rid:[0x%x]\n", alias_rids[i]); } done: return result; }
static NTSTATUS cmd_samr_delete_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, char **argv) { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; POLICY_HND connect_pol, domain_pol, user_pol; if (argc != 2) { printf("Usage: %s username\n", argv[0]); return NT_STATUS_OK; } /* Get sam policy and domain handles */ result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } /* Get handle on user */ { uint32 *user_rids, num_rids, *name_types; uint32 flags = 0x000003e8; /* Unknown */ result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, flags, 1, (const char **)&argv[1], &num_rids, &user_rids, &name_types); if (!NT_STATUS_IS_OK(result)) { goto done; } result = cli_samr_open_user(cli, mem_ctx, &domain_pol, MAXIMUM_ALLOWED_ACCESS, user_rids[0], &user_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } } /* Delete user */ result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } /* Display results */ done: return result; }
static NTSTATUS cmd_samr_enum_dom_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { POLICY_HND connect_pol, domain_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 start_idx, size, num_dom_groups, i; uint32 access_mask = MAXIMUM_ALLOWED_ACCESS; struct acct_info *dom_groups; BOOL got_connect_pol = False, got_domain_pol = False; if ((argc < 1) || (argc > 2)) { printf("Usage: %s [access_mask]\n", argv[0]); return NT_STATUS_OK; } if (argc > 1) sscanf(argv[1], "%x", &access_mask); /* Get sam policy handle */ result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) goto done; got_connect_pol = True; /* Get domain policy handle */ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, access_mask, &domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) goto done; got_domain_pol = True; /* Enumerate domain groups */ start_idx = 0; size = 0xffff; do { result = cli_samr_enum_dom_groups( cli, mem_ctx, &domain_pol, &start_idx, size, &dom_groups, &num_dom_groups); if (NT_STATUS_IS_OK(result) || NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) { for (i = 0; i < num_dom_groups; i++) printf("group:[%s] rid:[0x%x]\n", dom_groups[i].acct_name, dom_groups[i].rid); } } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)); done: if (got_domain_pol) cli_samr_close(cli, mem_ctx, &domain_pol); if (got_connect_pol) cli_samr_close(cli, mem_ctx, &connect_pol); return result; }
static int join_domain_byuser(char *domain, const char *remote, char *username, char *password) { /* libsmb variables */ pstring pdc_name; struct nmb_name calling, called; struct ntuser_creds creds; struct cli_state cli; fstring acct_name; struct in_addr dest_ip; TALLOC_CTX *mem_ctx; /* rpc variables */ POLICY_HND lsa_pol, sam_pol, domain_pol, user_pol; DOM_SID domain_sid; uint32 user_rid; /* Password stuff */ char *machine_pwd; int plen = 0; uchar pwbuf[516], ntpw[16], sess_key[16]; SAM_USERINFO_CTR ctr; SAM_USER_INFO_24 p24; SAM_USER_INFO_10 p10; /* Misc */ NTSTATUS result; int retval = 1; pstrcpy(pdc_name, remote ? remote : ""); /* Connect to remote machine */ ZERO_STRUCT(cli); ZERO_STRUCT(creds); ZERO_STRUCT(dest_ip); /* Make sure no nasty surprises */ if (!(mem_ctx = talloc_init())) { DEBUG(0, ("Could not initialise talloc context\n")); goto done; } if (!cli_initialise(&cli)) { DEBUG(0, ("Could not initialise client structure\n")); goto done; } init_rpcclient_creds(&creds, username, domain, password); cli_init_creds(&cli, &creds); /* * If we are given a remote machine assume this is the PDC. */ if(remote == NULL || !strcmp(remote, "*")) { struct in_addr *ip_list; int addr_count; if (!get_dc_list(True /* PDC only*/, domain, &ip_list, &addr_count)) { fprintf(stderr, "Unable to find the domain controller for domain %s.\n", domain); return 1; } if ((addr_count < 1) || (is_zero_ip(ip_list[0]))) { fprintf(stderr, "Incorrect entries returned when finding the domain controller for domain %s.\n", domain); return 1; } if (!lookup_dc_name(global_myname, domain, &ip_list[0], pdc_name)) { fprintf(stderr, "Unable to lookup the name for the domain controller for domain %s.\n", domain); return 1; } dest_ip = ip_list[0]; } make_nmb_name(&called, pdc_name, 0x20); make_nmb_name(&calling, dns_to_netbios_name(global_myname), 0); if (!cli_establish_connection(&cli, pdc_name, &dest_ip, &calling, &called, "IPC$", "IPC", False, True)) { if (!NT_STATUS_IS_OK(cli_nt_error(&cli))) { DEBUG(0, ("Error connecting to %s - %s\n", pdc_name,cli_errstr(&cli))); } else { DEBUG(0, ("Error connecting to %s\n", pdc_name)); } goto done; } /* Fetch domain sid */ if (!cli_nt_session_open(&cli, PIPE_LSARPC)) { DEBUG(0, ("Error connecting to SAM pipe\n")); goto done; } CHECK_RPC_ERR(cli_lsa_open_policy(&cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol), "error opening lsa policy handle"); CHECK_RPC_ERR(cli_lsa_query_info_policy(&cli, mem_ctx, &lsa_pol, 5, domain, &domain_sid), "error querying info policy"); cli_lsa_close(&cli, mem_ctx, &lsa_pol); cli_nt_session_close(&cli); /* Done with this pipe */ /* Create domain user */ if (!cli_nt_session_open(&cli, PIPE_SAMR)) { DEBUG(0, ("Error connecting to SAM pipe\n")); goto done; } CHECK_RPC_ERR(cli_samr_connect(&cli, mem_ctx, SEC_RIGHTS_MAXIMUM_ALLOWED, &sam_pol), "could not connect to SAM database"); CHECK_RPC_ERR(cli_samr_open_domain(&cli, mem_ctx, &sam_pol, SEC_RIGHTS_MAXIMUM_ALLOWED, &domain_sid, &domain_pol), "could not open domain"); /* Create domain user */ fstrcpy(acct_name, global_myname); fstrcat(acct_name, "$"); strlower(acct_name); { uint32 unknown = 0xe005000b; result = cli_samr_create_dom_user(&cli, mem_ctx, &domain_pol, acct_name, ACB_WSTRUST, unknown, &user_pol, &user_rid); } if (NT_STATUS_IS_OK(result)) { /* We *must* do this.... don't ask... */ CHECK_RPC_ERR_DEBUG(cli_samr_close(&cli, mem_ctx, &user_pol), ("error closing user policy")); result = NT_STATUS_USER_EXISTS; } if (NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_USER_EXISTS)) { uint32 num_rids, *name_types, *user_rids; uint32 flags = 0x3e8; const char *names; /* Look up existing rid */ names = (char *)&acct_name[0]; CHECK_RPC_ERR_DEBUG( cli_samr_lookup_names(&cli, mem_ctx, &domain_pol, flags, 1, &names, &num_rids, &user_rids, &name_types), ("error looking up rid for user %s: %s\n", acct_name, get_nt_error_msg(result))); if (name_types[0] != SID_NAME_USER) { DEBUG(0, ("%s is not a user account\n", acct_name)); goto done; } user_rid = user_rids[0]; /* Open handle on user */ CHECK_RPC_ERR_DEBUG( cli_samr_open_user(&cli, mem_ctx, &domain_pol, SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol), ("could not re-open existing user %s: %s\n", acct_name, get_nt_error_msg(result))); } else if (!NT_STATUS_IS_OK(result)) { DEBUG(0, ("error creating domain user: %s\n", get_nt_error_msg(result))); goto done; } /* Create a random machine account password */ { UNISTR2 upw; /* Unicode password */ upw.buffer = (uint16 *)talloc_zero(mem_ctx, 0xc * sizeof(uint16)); upw.uni_str_len = 0xc; upw.uni_max_len = 0xc; machine_pwd = (char *)upw.buffer; plen = upw.uni_str_len * 2; generate_random_buffer((unsigned char *)machine_pwd, plen, True); encode_pw_buffer((char *)pwbuf, machine_pwd, plen, False); mdfour( ntpw, (unsigned char *)upw.buffer, plen); } /* Set password on machine account */ ZERO_STRUCT(ctr); ZERO_STRUCT(p24); init_sam_user_info24(&p24, (char *)pwbuf,24); ctr.switch_value = 24; ctr.info.id24 = &p24; /* I don't think this is quite the right place for this calculation. It should be moved somewhere where the credentials are calculated. )-: */ mdfour(sess_key, cli.pwd.smb_nt_pwd, 16); CHECK_RPC_ERR(cli_samr_set_userinfo(&cli, mem_ctx, &user_pol, 24, sess_key, &ctr), "error setting trust account password"); /* Why do we have to try to (re-)set the ACB to be the same as what we passed in the samr_create_dom_user() call? When a NT workstation is joined to a domain by an administrator the acb_info is set to 0x80. For a normal user with "Add workstations to the domain" rights the acb_info is 0x84. I'm not sure whether it is supposed to make a difference or not. NT seems to cope with either value so don't bomb out if the set userinfo2 level 0x10 fails. -tpot */ ZERO_STRUCT(ctr); ctr.switch_value = 0x10; ctr.info.id10 = &p10; init_sam_user_info10(&p10, ACB_WSTRUST); /* Ignoring the return value is necessary for joining a domain as a normal user with "Add workstation to domain" privilege. */ result = cli_samr_set_userinfo2(&cli, mem_ctx, &user_pol, 0x10, sess_key, &ctr); /* Now store the secret in the secrets database */ strupper(domain); if (!secrets_store_domain_sid(domain, &domain_sid) || !secrets_store_trust_account_password(domain, ntpw)) { DEBUG(0, ("error storing domain secrets\n")); goto done; } retval = 0; /* Success! */ done: /* Close down pipe - this will clean up open policy handles */ if (cli.nt_pipe_fnum) cli_nt_session_close(&cli); /* Display success or failure */ if (retval != 0) { trust_password_delete(domain); fprintf(stderr,"Unable to join domain %s.\n",domain); } else { printf("Joined domain %s.\n",domain); } return retval; }
/* Lookup user information from a rid or username. */ static NTSTATUS query_user(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const DOM_SID *user_sid, WINBIND_USERINFO *user_info) { CLI_POLICY_HND *hnd = NULL; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; POLICY_HND dom_pol, user_pol; BOOL got_dom_pol = False, got_user_pol = False; SAM_USERINFO_CTR *ctr; int retry; fstring sid_string; uint32 user_rid; NET_USER_INFO_3 *user; DEBUG(3,("rpc: query_user rid=%s\n", sid_to_string(sid_string, user_sid))); if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) { goto done; } /* try netsamlogon cache first */ if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL ) { DEBUG(5,("query_user: Cache lookup succeeded for %s\n", sid_string_static(user_sid))); user_info->user_sid = rid_to_talloced_sid( domain, mem_ctx, user_rid ); user_info->group_sid = rid_to_talloced_sid( domain, mem_ctx, user->group_rid ); user_info->acct_name = unistr2_tdup(mem_ctx, &user->uni_user_name); user_info->full_name = unistr2_tdup(mem_ctx, &user->uni_full_name); SAFE_FREE(user); return NT_STATUS_OK; } /* no cache; hit the wire */ retry = 0; do { /* Get sam handle; if we fail here there is no hope */ if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd))) goto done; /* Get domain handle */ result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, SEC_RIGHTS_MAXIMUM_ALLOWED, &domain->sid, &dom_pol); } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); if (!NT_STATUS_IS_OK(result)) goto done; got_dom_pol = True; /* Get user handle */ result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol, SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol); if (!NT_STATUS_IS_OK(result)) goto done; got_user_pol = True; /* Get user info */ result = cli_samr_query_userinfo(hnd->cli, mem_ctx, &user_pol, 0x15, &ctr); if (!NT_STATUS_IS_OK(result)) goto done; cli_samr_close(hnd->cli, mem_ctx, &user_pol); got_user_pol = False; user_info->user_sid = rid_to_talloced_sid(domain, mem_ctx, user_rid); user_info->group_sid = rid_to_talloced_sid(domain, mem_ctx, ctr->info.id21->group_rid); user_info->acct_name = unistr2_tdup(mem_ctx, &ctr->info.id21->uni_user_name); user_info->full_name = unistr2_tdup(mem_ctx, &ctr->info.id21->uni_full_name); done: /* Clean up policy handles */ if (got_user_pol) cli_samr_close(hnd->cli, mem_ctx, &user_pol); if (got_dom_pol) cli_samr_close(hnd->cli, mem_ctx, &dom_pol); return result; }
static NTSTATUS cmd_samr_query_dispinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, char **argv) { POLICY_HND connect_pol, domain_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 start_idx=0, max_entries=250, max_size = 0xffff, num_entries, i; int info_level = 1; SAM_DISPINFO_CTR ctr; SAM_DISPINFO_1 info1; SAM_DISPINFO_2 info2; SAM_DISPINFO_3 info3; SAM_DISPINFO_4 info4; SAM_DISPINFO_5 info5; int loop_count = 0; BOOL got_params = False; /* Use get_query_dispinfo_params() or not? */ if (argc > 4) { printf("Usage: %s [info level] [start index] [max entries] [max_size]\n", argv[0]); return NT_STATUS_OK; } if (argc >= 2) sscanf(argv[1], "%i", &info_level); if (argc >= 3) sscanf(argv[2], "%i", &start_idx); if (argc >= 4) { sscanf(argv[3], "%i", &max_entries); got_params = True; } if (argc >= 5) { sscanf(argv[4], "%i", &max_size); got_params = True; } /* Get sam policy handle */ result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } /* Get domain policy handle */ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } /* Query display info */ ZERO_STRUCT(ctr); ZERO_STRUCT(info1); switch (info_level) { case 1: ZERO_STRUCT(info1); ctr.sam.info1 = &info1; break; case 2: ZERO_STRUCT(info2); ctr.sam.info2 = &info2; break; case 3: ZERO_STRUCT(info3); ctr.sam.info3 = &info3; break; case 4: ZERO_STRUCT(info4); ctr.sam.info4 = &info4; break; case 5: ZERO_STRUCT(info5); ctr.sam.info5 = &info5; break; } do { if (!got_params) get_query_dispinfo_params( loop_count, &max_entries, &max_size); result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol, &start_idx, info_level, &num_entries, max_entries, max_size, &ctr); loop_count++; for (i = 0; i < num_entries; i++) { switch (info_level) { case 1: display_sam_info_1(&ctr.sam.info1->sam[i], &ctr.sam.info1->str[i]); break; case 2: display_sam_info_2(&ctr.sam.info2->sam[i], &ctr.sam.info2->str[i]); break; case 3: display_sam_info_3(&ctr.sam.info3->sam[i], &ctr.sam.info3->str[i]); break; case 4: display_sam_info_4(&ctr.sam.info4->sam[i], &ctr.sam.info4->str[i]); break; case 5: display_sam_info_5(&ctr.sam.info5->sam[i], &ctr.sam.info5->str[i]); break; } } } while (!NT_STATUS_IS_OK(result)); done: return result; }
/* Lookup groups a user is a member of. I wish Unix had a call like this! */ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const DOM_SID *user_sid, uint32 *num_groups, DOM_SID ***user_grpsids) { CLI_POLICY_HND *hnd; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; POLICY_HND dom_pol, user_pol; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; BOOL got_dom_pol = False, got_user_pol = False; DOM_GID *user_groups; unsigned int i; unsigned int retry; fstring sid_string; uint32 user_rid; NET_USER_INFO_3 *user; DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_to_string(sid_string, user_sid))); *num_groups = 0; *user_grpsids = NULL; /* so lets see if we have a cached user_info_3 */ if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL ) { DEBUG(5,("query_user: Cache lookup succeeded for %s\n", sid_string_static(user_sid))); *num_groups = user->num_groups; (*user_grpsids) = talloc(mem_ctx, sizeof(DOM_SID*) * (*num_groups)); for (i=0;i<(*num_groups);i++) { (*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user->gids[i].g_rid); } SAFE_FREE(user); return NT_STATUS_OK; } /* no cache; hit the wire */ retry = 0; do { /* Get sam handle; if we fail here there is no hope */ if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd))) goto done; /* Get domain handle */ result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, des_access, &domain->sid, &dom_pol); } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); if (!NT_STATUS_IS_OK(result)) goto done; got_dom_pol = True; if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) { goto done; } /* Get user handle */ result = cli_samr_open_user(hnd->cli, mem_ctx, &dom_pol, des_access, user_rid, &user_pol); if (!NT_STATUS_IS_OK(result)) goto done; got_user_pol = True; /* Query user rids */ result = cli_samr_query_usergroups(hnd->cli, mem_ctx, &user_pol, num_groups, &user_groups); if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0) goto done; (*user_grpsids) = talloc(mem_ctx, sizeof(DOM_SID*) * (*num_groups)); if (!(*user_grpsids)) { result = NT_STATUS_NO_MEMORY; goto done; } for (i=0;i<(*num_groups);i++) { (*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user_groups[i].g_rid); } done: /* Clean up policy handles */ if (got_user_pol) cli_samr_close(hnd->cli, mem_ctx, &user_pol); if (got_dom_pol) cli_samr_close(hnd->cli, mem_ctx, &dom_pol); return result; }
static NTSTATUS cmd_samr_query_dominfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, char **argv) { POLICY_HND connect_pol, domain_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; int switch_value = 2; SAM_UNK_CTR ctr; if (argc > 2) { printf("Usage: %s [infolevel]\n", argv[0]); return NT_STATUS_OK; } if (argc == 2) sscanf(argv[1], "%i", &switch_value); /* Get sam policy handle */ result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } /* Get domain policy handle */ result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } /* Query domain info */ result = cli_samr_query_dom_info(cli, mem_ctx, &domain_pol, switch_value, &ctr); if (!NT_STATUS_IS_OK(result)) { goto done; } /* Display domain info */ switch (switch_value) { case 1: display_sam_unk_info_1(&ctr.info.inf1); break; case 2: display_sam_unk_info_2(&ctr.info.inf2); break; default: printf("cannot display domain info for switch value %d\n", switch_value); break; } done: cli_samr_close(cli, mem_ctx, &domain_pol); cli_samr_close(cli, mem_ctx, &connect_pol); return result; }
/* find the sequence number for a domain */ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) { TALLOC_CTX *mem_ctx; CLI_POLICY_HND *hnd; SAM_UNK_CTR ctr; uint16 switch_value = 2; NTSTATUS result; POLICY_HND dom_pol; BOOL got_dom_pol = False; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; int retry; DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name)); *seq = DOM_SEQUENCE_NONE; if (!(mem_ctx = talloc_init("sequence_number[rpc]"))) return NT_STATUS_NO_MEMORY; retry = 0; do { #ifdef HAVE_LDAP if ( domain->native_mode ) { DEBUG(8,("using get_ldap_seq() to retrieve the sequence number\n")); if ( get_ldap_sequence_number( domain->name, seq ) == 0 ) { result = NT_STATUS_OK; DEBUG(10,("domain_sequence_number: LDAP for domain %s is %u\n", domain->name, *seq)); goto done; } DEBUG(10,("domain_sequence_number: failed to get LDAP sequence number for domain %s\n", domain->name )); } #endif /* HAVE_LDAP */ /* Get sam handle */ if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd))) goto done; /* Get domain handle */ result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, des_access, &domain->sid, &dom_pol); } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); if (!NT_STATUS_IS_OK(result)) goto done; got_dom_pol = True; /* Query domain info */ result = cli_samr_query_dom_info(hnd->cli, mem_ctx, &dom_pol, switch_value, &ctr); if (NT_STATUS_IS_OK(result)) { *seq = ctr.info.inf2.seq_num; DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)*seq)); } else { DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n", (unsigned)*seq, domain->name )); } done: if (got_dom_pol) cli_samr_close(hnd->cli, mem_ctx, &dom_pol); talloc_destroy(mem_ctx); return result; }
static NTSTATUS cmd_samr_enum_als_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { POLICY_HND connect_pol, domain_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 start_idx, size, num_als_groups, i; uint32 access_mask = MAXIMUM_ALLOWED_ACCESS; struct acct_info *als_groups; DOM_SID global_sid_Builtin; BOOL got_connect_pol = False, got_domain_pol = False; string_to_sid(&global_sid_Builtin, "S-1-5-32"); if ((argc < 2) || (argc > 3)) { printf("Usage: %s builtin|domain [access mask]\n", argv[0]); return NT_STATUS_OK; } if (argc > 2) sscanf(argv[2], "%x", &access_mask); /* Get sam policy handle */ result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) goto done; got_connect_pol = True; /* Get domain policy handle */ if (StrCaseCmp(argv[1], "domain")==0) result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, access_mask, &domain_sid, &domain_pol); else if (StrCaseCmp(argv[1], "builtin")==0) result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, access_mask, &global_sid_Builtin, &domain_pol); else return NT_STATUS_OK; if (!NT_STATUS_IS_OK(result)) goto done; got_domain_pol = True; /* Enumerate alias groups */ start_idx = 0; size = 0xffff; /* Number of groups to retrieve */ do { result = cli_samr_enum_als_groups( cli, mem_ctx, &domain_pol, &start_idx, size, &als_groups, &num_als_groups); if (NT_STATUS_IS_OK(result) || NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)) { for (i = 0; i < num_als_groups; i++) printf("group:[%s] rid:[0x%x]\n", als_groups[i].acct_name, als_groups[i].rid); } } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)); done: if (got_domain_pol) cli_samr_close(cli, mem_ctx, &domain_pol); if (got_connect_pol) cli_samr_close(cli, mem_ctx, &connect_pol); return result; }