Esempio n. 1
0
int netdom_store_machine_account( const char *domain, DOM_SID *sid, const char *pw )
{
	if (!secrets_store_domain_sid(domain, sid)) {
		DEBUG(1,("Failed to save domain sid\n"));
		return -1;
	}

	if (!secrets_store_machine_password(pw, domain, SEC_CHAN_WKSTA)) {
		DEBUG(1,("Failed to save machine password\n"));
		return -1;
	}

	return 0;
}
Esempio n. 2
0
static int net_setdomainsid(struct net_context *c, int argc, const char **argv)
{
	DOM_SID sid;

	if ( (argc != 1)
	     || (strncmp(argv[0], "S-1-5-21-", strlen("S-1-5-21-")) != 0)
	     || (!string_to_sid(&sid, argv[0]))
	     || (sid.num_auths != 4)) {
		d_printf("usage: net setdomainsid S-1-5-21-x-y-z\n");
		return 1;
	}

	if (!secrets_store_domain_sid(lp_workgroup(), &sid)) {
		DEBUG(0,("Can't store domain SID.\n"));
		return 1;
	}

	return 0;
}
Esempio n. 3
0
File: net.c Progetto: AllardJ/Tomato
static int net_setlocalsid(int argc, const char **argv)
{
	DOM_SID sid;

	if ( (argc != 1)
	     || (strncmp(argv[0], "S-1-5-21-", strlen("S-1-5-21-")) != 0)
	     || (!string_to_sid(&sid, argv[0]))
	     || (sid.num_auths != 4)) {
		d_printf("usage: net setlocalsid S-1-5-21-x-y-z\n");
		return 1;
	}

	if (!secrets_store_domain_sid(global_myname(), &sid)) {
		DEBUG(1,("Can't store domain SID as a pdc/bdc.\n"));
		return 1;
	}

	return 0;
}
Esempio n. 4
0
static int net_setlocalsid(struct net_context *c, int argc, const char **argv)
{
	struct dom_sid sid;

	if ( (argc != 1)
	     || (strncmp(argv[0], "S-1-5-21-", strlen("S-1-5-21-")) != 0)
	     || (!string_to_sid(&sid, argv[0]))
	     || (sid.num_auths != 4)) {
		d_printf(_("Usage:"));
		d_printf(" net setlocalsid S-1-5-21-x-y-z\n");
		return 1;
	}

	if (!secrets_store_domain_sid(lp_netbios_name(), &sid)) {
		DEBUG(0,("Can't store domain SID as a pdc/bdc.\n"));
		return 1;
	}

	return 0;
}
Esempio n. 5
0
int net_rpc_join_newstyle(struct net_context *c, int argc, const char **argv)
{

	/* libsmb variables */

	struct cli_state *cli;
	TALLOC_CTX *mem_ctx;
        uint32 acb_info = ACB_WSTRUST;
	uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
	enum netr_SchannelType sec_channel_type;
	struct rpc_pipe_client *pipe_hnd = NULL;
	struct dcerpc_binding_handle *b = NULL;

	/* rpc variables */

	struct policy_handle lsa_pol, sam_pol, domain_pol, user_pol;
	struct dom_sid *domain_sid;
	uint32 user_rid;

	/* Password stuff */

	char *clear_trust_password = NULL;
	struct samr_CryptPassword crypt_pwd;
	uchar md4_trust_password[16];
	union samr_UserInfo set_info;

	/* Misc */

	NTSTATUS status, result;
	int retval = 1;
	const char *domain = NULL;
	char *acct_name;
	struct lsa_String lsa_acct_name;
	uint32 acct_flags=0;
	uint32_t access_granted = 0;
	union lsa_PolicyInformation *info = NULL;
	struct samr_Ids user_rids;
	struct samr_Ids name_types;


	/* 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
	default:
		DEBUG(0,("secure channel type %d not yet supported\n",
			sec_channel_type));
		break;
	}

	/* Make authenticated connection to remote machine */

	status = net_make_ipc_connection(c, NET_FLAGS_PDC, &cli);
	if (!NT_STATUS_IS_OK(status)) {
		return 1;
	}

	if (!(mem_ctx = talloc_init("net_rpc_join_newstyle"))) {
		DEBUG(0, ("Could not initialise talloc context\n"));
		goto done;
	}

	/* Fetch domain sid */

	status = cli_rpc_pipe_open_noauth(cli, &ndr_table_lsarpc.syntax_id,
					  &pipe_hnd);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Error connecting to LSA pipe. Error was %s\n",
			nt_errstr(status) ));
		goto done;
	}

	b = pipe_hnd->binding_handle;

	CHECK_RPC_ERR(rpccli_lsa_open_policy(pipe_hnd, mem_ctx, true,
					  SEC_FLAG_MAXIMUM_ALLOWED,
					  &lsa_pol),
		      "error opening lsa policy handle");

	CHECK_DCERPC_ERR(dcerpc_lsa_QueryInfoPolicy(b, mem_ctx,
						    &lsa_pol,
						    LSA_POLICY_INFO_ACCOUNT_DOMAIN,
						    &info,
						    &result),
		      "error querying info policy");

	domain = info->account_domain.name.string;
	domain_sid = info->account_domain.sid;

	dcerpc_lsa_Close(b, mem_ctx, &lsa_pol, &result);
	TALLOC_FREE(pipe_hnd); /* Done with this pipe */

	/* Bail out if domain didn't get set. */
	if (!domain) {
		DEBUG(0, ("Could not get domain name.\n"));
		goto done;
	}

	/* Create domain user */
	status = cli_rpc_pipe_open_noauth(cli, &ndr_table_samr.syntax_id,
					  &pipe_hnd);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n",
			nt_errstr(status) ));
		goto done;
	}

	b = pipe_hnd->binding_handle;

	CHECK_DCERPC_ERR(dcerpc_samr_Connect2(b, mem_ctx,
					      pipe_hnd->desthost,
					      SAMR_ACCESS_ENUM_DOMAINS
					      | SAMR_ACCESS_LOOKUP_DOMAIN,
					      &sam_pol,
					      &result),
		      "could not connect to SAM database");


	CHECK_DCERPC_ERR(dcerpc_samr_OpenDomain(b, mem_ctx,
						&sam_pol,
						SAMR_DOMAIN_ACCESS_LOOKUP_INFO_1
						| SAMR_DOMAIN_ACCESS_CREATE_USER
						| SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
						domain_sid,
						&domain_pol,
						&result),
		      "could not open domain");

	/* Create domain user */
	if ((acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname())) == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}
	strlower_m(acct_name);

	init_lsa_String(&lsa_acct_name, acct_name);

	acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
		     SEC_STD_WRITE_DAC | SEC_STD_DELETE |
		     SAMR_USER_ACCESS_SET_PASSWORD |
		     SAMR_USER_ACCESS_GET_ATTRIBUTES |
		     SAMR_USER_ACCESS_SET_ATTRIBUTES;

	DEBUG(10, ("Creating account with flags: %d\n",acct_flags));

	status = dcerpc_samr_CreateUser2(b, mem_ctx,
					 &domain_pol,
					 &lsa_acct_name,
					 acb_info,
					 acct_flags,
					 &user_pol,
					 &access_granted,
					 &user_rid,
					 &result);
	if (!NT_STATUS_IS_OK(status)) {
		goto done;
	}
	if (!NT_STATUS_IS_OK(result) &&
	    !NT_STATUS_EQUAL(result, NT_STATUS_USER_EXISTS)) {
		status = result;
		d_fprintf(stderr,_("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_fprintf(stderr, _("User specified does not have "
					    "administrator privileges\n"));

		goto done;
	}

	/* We *must* do this.... don't ask... */

	if (NT_STATUS_IS_OK(result)) {
		dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
	}

	CHECK_DCERPC_ERR_DEBUG(dcerpc_samr_LookupNames(b, mem_ctx,
						       &domain_pol,
						       1,
						       &lsa_acct_name,
						       &user_rids,
						       &name_types,
						       &result),
			    ("error looking up rid for user %s: %s/%s\n",
			     acct_name, nt_errstr(status), nt_errstr(result)));

	if (user_rids.count != 1) {
		status = NT_STATUS_INVALID_NETWORK_RESPONSE;
		goto done;
	}
	if (name_types.count != 1) {
		status = NT_STATUS_INVALID_NETWORK_RESPONSE;
		goto done;
	}

	if (name_types.ids[0] != SID_NAME_USER) {
		DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types.ids[0]));
		goto done;
	}

	user_rid = user_rids.ids[0];

	/* Open handle on user */

	CHECK_DCERPC_ERR_DEBUG(
		dcerpc_samr_OpenUser(b, mem_ctx,
				     &domain_pol,
				     SEC_FLAG_MAXIMUM_ALLOWED,
				     user_rid,
				     &user_pol,
				     &result),
		("could not re-open existing user %s: %s/%s\n",
		 acct_name, nt_errstr(status), nt_errstr(result)));
	
	/* Create a random machine account password */

	clear_trust_password = generate_random_str(talloc_tos(), DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
	E_md4hash(clear_trust_password, md4_trust_password);

	/* Set password on machine account */

	init_samr_CryptPassword(clear_trust_password,
				&cli->user_session_key,
				&crypt_pwd);

	set_info.info24.password = crypt_pwd;
	set_info.info24.password_expired = PASS_DONT_CHANGE_AT_NEXT_LOGON;

	CHECK_DCERPC_ERR(dcerpc_samr_SetUserInfo2(b, mem_ctx,
						  &user_pol,
						  24,
						  &set_info,
						  &result),
		      "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 */

	set_info.info16.acct_flags = acb_info;

	/* Ignoring the return value is necessary for joining a domain
	   as a normal user with "Add workstation to domain" privilege. */

	status = dcerpc_samr_SetUserInfo(b, mem_ctx,
					 &user_pol,
					 16,
					 &set_info,
					 &result);

	dcerpc_samr_Close(b, mem_ctx, &user_pol, &result);
	TALLOC_FREE(pipe_hnd); /* Done with this pipe */

	/* Now check the whole process from top-to-bottom */

	status = cli_rpc_pipe_open_noauth(cli, &ndr_table_netlogon.syntax_id,
					  &pipe_hnd);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0,("Error connecting to NETLOGON pipe. Error was %s\n",
			nt_errstr(status) ));
		goto done;
	}

	status = rpccli_netlogon_setup_creds(pipe_hnd,
					cli->desthost, /* server name */
					domain,        /* domain */
					global_myname(), /* client name */
					global_myname(), /* machine account name */
                                        md4_trust_password,
                                        sec_channel_type,
                                        &neg_flags);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Error in domain join verification (credential setup failed): %s\n\n",
			  nt_errstr(status)));

		if ( NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
		     (sec_channel_type == SEC_CHAN_BDC) ) {
			d_fprintf(stderr, _("Please make sure that no computer "
					    "account\nnamed like this machine "
					    "(%s) exists in the domain\n"),
				 global_myname());
		}

		goto done;
	}

	/* We can only check the schannel connection if the client is allowed
	   to do this and the server supports it. If not, just assume success
	   (after all the rpccli_netlogon_setup_creds() succeeded, and we'll
	   do the same again (setup creds) in net_rpc_join_ok(). JRA. */

	if (lp_client_schannel() && (neg_flags & NETLOGON_NEG_SCHANNEL)) {
		struct rpc_pipe_client *netlogon_schannel_pipe;

		status = cli_rpc_pipe_open_schannel_with_key(
			cli, &ndr_table_netlogon.syntax_id, NCACN_NP,
			DCERPC_AUTH_LEVEL_PRIVACY, domain, &pipe_hnd->dc,
			&netlogon_schannel_pipe);

		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(0, ("Error in domain join verification (schannel setup failed): %s\n\n",
				  nt_errstr(status)));

			if ( NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
			     (sec_channel_type == SEC_CHAN_BDC) ) {
				d_fprintf(stderr, _("Please make sure that no "
						    "computer account\nnamed "
						    "like this machine (%s) "
						    "exists in the domain\n"),
					 global_myname());
			}

			goto done;
		}
		TALLOC_FREE(netlogon_schannel_pipe);
	}

	TALLOC_FREE(pipe_hnd);

	/* Now store the secret in the secrets database */

	strupper_m(CONST_DISCARD(char *, 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 */
	status = net_rpc_join_ok(c, domain, cli->desthost, &cli->dest_ss);
	retval = NT_STATUS_IS_OK(status) ? 0 : -1;

done:

	/* Display success or failure */

	if (domain) {
		if (retval != 0) {
			fprintf(stderr,_("Unable to join domain %s.\n"),domain);
		} else {
			printf(_("Joined domain %s.\n"),domain);
		}
	}

	cli_shutdown(cli);

	TALLOC_FREE(clear_trust_password);

	return retval;
}
Esempio n. 6
0
/*
  join a domain using ADS
 */
int net_ads_join(int argc, const char **argv)
{
	ADS_STRUCT *ads;
	ADS_STATUS rc;
	char *password;
	char *machine_account = NULL;
	char *tmp_password;
	const char *org_unit = "Computers";
	char *dn;
	void *res;
	DOM_SID dom_sid;
	char *ou_str;
	uint32 sec_channel_type = SEC_CHAN_WKSTA;
	uint32 account_type = UF_WORKSTATION_TRUST_ACCOUNT;
	const char *short_domain_name = NULL;
	TALLOC_CTX *ctx = NULL;

	if (argc > 0) {
		org_unit = argv[0];
	}

	if (!secrets_init()) {
		DEBUG(1,("Failed to initialise secrets database\n"));
		return -1;
	}

	tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
	password = strdup(tmp_password);

	if (!(ads = ads_startup())) {
		return -1;
	}

	if (!*lp_realm()) {
		d_printf("realm must be set in in smb.conf for ADS join to succeed.\n");
		ads_destroy(&ads);
		return -1;
	}

	if (strcmp(ads->config.realm, lp_realm()) != 0) {
		d_printf("realm of remote server (%s) and realm in smb.conf (%s) DO NOT match.  Aborting join\n", ads->config.realm, lp_realm());
		ads_destroy(&ads);
		return -1;
	}

	ou_str = ads_ou_string(org_unit);
	asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path);
	free(ou_str);

	rc = ads_search_dn(ads, &res, dn, NULL);
	ads_msgfree(ads, res);

	if (rc.error_type == ENUM_ADS_ERROR_LDAP && rc.err.rc == LDAP_NO_SUCH_OBJECT) {
		d_printf("ads_join_realm: organizational unit %s does not exist (dn:%s)\n", 
			 org_unit, dn);
		ads_destroy(&ads);
		return -1;
	}
	free(dn);

	if (!ADS_ERR_OK(rc)) {
		d_printf("ads_join_realm: %s\n", ads_errstr(rc));
		ads_destroy(&ads);
		return -1;
	}	

	rc = ads_join_realm(ads, global_myname(), account_type, org_unit);
	if (!ADS_ERR_OK(rc)) {
		d_printf("ads_join_realm: %s\n", ads_errstr(rc));
		ads_destroy(&ads);
		return -1;
	}

	rc = ads_domain_sid(ads, &dom_sid);
	if (!ADS_ERR_OK(rc)) {
		d_printf("ads_domain_sid: %s\n", ads_errstr(rc));	
		ads_destroy(&ads);
		return -1;
	}

	if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
		d_printf("asprintf failed\n");
		ads_destroy(&ads);
		return -1;
	}

	rc = ads_set_machine_password(ads, machine_account, password);
	if (!ADS_ERR_OK(rc)) {
		d_printf("ads_set_machine_password: %s\n", ads_errstr(rc));
		ads_destroy(&ads);
		return -1;
	}
	
	/* make sure we get the right workgroup */
	
	if ( !(ctx = talloc_init("net ads join")) ) {
		d_printf("talloc_init() failed!\n");
		ads_destroy(&ads);
		return -1;
	}
	
	rc = ads_workgroup_name(ads, ctx, &short_domain_name);
	if ( ADS_ERR_OK(rc) ) {
		if ( !strequal(lp_workgroup(), short_domain_name) ) {
			d_printf("The workgroup in smb.conf does not match the short\n");
			d_printf("domain name obtained from the server.\n");
			d_printf("Using the name [%s] from the server.\n", short_domain_name);
			d_printf("You should set \"workgroup = %s\" in smb.conf.\n", short_domain_name);
		}
	} else {
		short_domain_name = lp_workgroup();
	}
	
	d_printf("Using short domain name -- %s\n", short_domain_name);
	
	/*  HACK ALRET!  Store the sid and password under bother the lp_workgroup() 
	    value from smb.conf and the string returned from the server.  The former is
	    neede to bootstrap winbindd's first connection to the DC to get the real 
	    short domain name   --jerry */
	    
	if (!secrets_store_domain_sid(lp_workgroup(), &dom_sid)) {
		DEBUG(1,("Failed to save domain sid\n"));
		ads_destroy(&ads);
		return -1;
	}

	if (!secrets_store_machine_password(password, lp_workgroup(), sec_channel_type)) {
		DEBUG(1,("Failed to save machine password\n"));
		ads_destroy(&ads);
		return -1;
	}

	if (!secrets_store_domain_sid(short_domain_name, &dom_sid)) {
		DEBUG(1,("Failed to save domain sid\n"));
		ads_destroy(&ads);
		return -1;
	}

	if (!secrets_store_machine_password(password, short_domain_name, sec_channel_type)) {
		DEBUG(1,("Failed to save machine password\n"));
		ads_destroy(&ads);
		return -1;
	}
	
	/* Now build the keytab, using the same ADS connection */
	if (lp_use_kerberos_keytab() && ads_keytab_create_default(ads)) {
		DEBUG(1,("Error creating host keytab!\n"));
	}

	d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->config.realm);

	SAFE_FREE(password);
	SAFE_FREE(machine_account);
	if ( ctx ) {
		talloc_destroy(ctx);
	}
	ads_destroy(&ads);
	return 0;
}
Esempio n. 7
0
static struct dom_sid *pdb_generate_sam_sid(void)
{
    struct dom_sid domain_sid;
    char *fname = NULL;
    struct dom_sid *sam_sid;

    if(!(sam_sid=SMB_MALLOC_P(struct dom_sid)))
        return NULL;

    if ( IS_DC ) {
        if (secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
            sid_copy(sam_sid, &domain_sid);
            return sam_sid;
        }
    }

    if (secrets_fetch_domain_sid(lp_netbios_name(), sam_sid)) {

        /* We got our sid. If not a pdc/bdc, we're done. */
        if ( !IS_DC )
            return sam_sid;

        if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {

            /* No domain sid and we're a pdc/bdc. Store it */

            if (!secrets_store_domain_sid(lp_workgroup(), sam_sid)) {
                DEBUG(0,("pdb_generate_sam_sid: Can't store domain SID as a pdc/bdc.\n"));
                SAFE_FREE(sam_sid);
                return NULL;
            }
            return sam_sid;
        }

        if (!dom_sid_equal(&domain_sid, sam_sid)) {

            /* Domain name sid doesn't match global sam sid. Re-store domain sid as 'local' sid. */

            DEBUG(0,("pdb_generate_sam_sid: Mismatched SIDs as a pdc/bdc.\n"));
            if (!secrets_store_domain_sid(lp_netbios_name(), &domain_sid)) {
                DEBUG(0,("pdb_generate_sam_sid: Can't re-store domain SID for local sid as PDC/BDC.\n"));
                SAFE_FREE(sam_sid);
                return NULL;
            }
            return sam_sid;
        }

        return sam_sid;
    }

    /* check for an old MACHINE.SID file for backwards compatibility */
    if (asprintf(&fname, "%s/MACHINE.SID", lp_private_dir()) == -1) {
        SAFE_FREE(sam_sid);
        return NULL;
    }

    if (read_sid_from_file(fname, sam_sid)) {
        /* remember it for future reference and unlink the old MACHINE.SID */
        if (!secrets_store_domain_sid(lp_netbios_name(), sam_sid)) {
            DEBUG(0,("pdb_generate_sam_sid: Failed to store SID from file.\n"));
            SAFE_FREE(fname);
            SAFE_FREE(sam_sid);
            return NULL;
        }
        unlink(fname);
        if ( !IS_DC ) {
            if (!secrets_store_domain_sid(lp_workgroup(), sam_sid)) {
                DEBUG(0,("pdb_generate_sam_sid: Failed to store domain SID from file.\n"));
                SAFE_FREE(fname);
                SAFE_FREE(sam_sid);
                return NULL;
            }
        }

        /* Stored the old sid from MACHINE.SID successfully.*/
        SAFE_FREE(fname);
        return sam_sid;
    }

    SAFE_FREE(fname);

    /* we don't have the SID in secrets.tdb, we will need to
           generate one and save it */
    generate_random_sid(sam_sid);

    if (!secrets_store_domain_sid(lp_netbios_name(), sam_sid)) {
        DEBUG(0,("pdb_generate_sam_sid: Failed to store generated machine SID.\n"));
        SAFE_FREE(sam_sid);
        return NULL;
    }
    if ( IS_DC ) {
        if (!secrets_store_domain_sid(lp_workgroup(), sam_sid)) {
            DEBUG(0,("pdb_generate_sam_sid: Failed to store generated domain SID.\n"));
            SAFE_FREE(sam_sid);
            return NULL;
        }
    }

    return sam_sid;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
static BOOL pdb_generate_sam_sid(void)
{
	DOM_SID domain_sid;
	char *fname = NULL;
	BOOL is_dc = False;

	if(global_sam_sid==NULL)
		if(!(global_sam_sid=(DOM_SID *)malloc(sizeof(DOM_SID))))
			return False;
			
	generate_wellknown_sids();

	switch (lp_server_role()) {
	case ROLE_DOMAIN_PDC:
	case ROLE_DOMAIN_BDC:
		is_dc = True;
		break;
	default:
		is_dc = False;
		break;
	}

	if (is_dc) {
		if (secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
			sid_copy(global_sam_sid, &domain_sid);
			return True;
		}
	}

	if (secrets_fetch_domain_sid(global_myname(), global_sam_sid)) {

		/* We got our sid. If not a pdc/bdc, we're done. */
		if (!is_dc)
			return True;

		if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {

			/* No domain sid and we're a pdc/bdc. Store it */

			if (!secrets_store_domain_sid(lp_workgroup(), global_sam_sid)) {
				DEBUG(0,("pdb_generate_sam_sid: Can't store domain SID as a pdc/bdc.\n"));
				return False;
			}
			return True;
		}

		if (!sid_equal(&domain_sid, global_sam_sid)) {

			/* Domain name sid doesn't match global sam sid. Re-store domain sid as 'local' sid. */

			DEBUG(0,("pdb_generate_sam_sid: Mismatched SIDs as a pdc/bdc.\n"));
			if (!secrets_store_domain_sid(global_myname(), &domain_sid)) {
				DEBUG(0,("pdb_generate_sam_sid: Can't re-store domain SID for local sid as PDC/BDC.\n"));
				return False;
			}
			return True;
		}

		return True;
		
	}

	/* check for an old MACHINE.SID file for backwards compatibility */
	asprintf(&fname, "%s/MACHINE.SID", lp_private_dir());

	if (read_sid_from_file(fname, global_sam_sid)) {
		/* remember it for future reference and unlink the old MACHINE.SID */
		if (!secrets_store_domain_sid(global_myname(), global_sam_sid)) {
			DEBUG(0,("pdb_generate_sam_sid: Failed to store SID from file.\n"));
			SAFE_FREE(fname);
			return False;
		}
		unlink(fname);
		if (is_dc) {
			if (!secrets_store_domain_sid(lp_workgroup(), global_sam_sid)) {
				DEBUG(0,("pdb_generate_sam_sid: Failed to store domain SID from file.\n"));
				SAFE_FREE(fname);
				return False;
			}
		}

		/* Stored the old sid from MACHINE.SID successfully.*/
		SAFE_FREE(fname);
		return True;
	}

	SAFE_FREE(fname);

	/* we don't have the SID in secrets.tdb, we will need to
           generate one and save it */
	generate_random_sid(global_sam_sid);

	if (!secrets_store_domain_sid(global_myname(), global_sam_sid)) {
		DEBUG(0,("pdb_generate_sam_sid: Failed to store generated machine SID.\n"));
		return False;
	}
	if (is_dc) {
		if (!secrets_store_domain_sid(lp_workgroup(), global_sam_sid)) {
			DEBUG(0,("pdb_generate_sam_sid: Failed to store generated domain SID.\n"));
			return False;
		}
	}

	return True;
}   
Esempio n. 10
0
BOOL pdb_generate_sam_sid(void)
{
	char *fname = NULL;
	extern pstring global_myname;
	extern fstring global_myworkgroup;
	BOOL is_dc = False;
	pstring priv_dir;

	generate_wellknown_sids();

	switch (lp_server_role()) {
	case ROLE_DOMAIN_PDC:
	case ROLE_DOMAIN_BDC:
		is_dc = True;
		break;
	default:
		is_dc = False;
		break;
	}

	if (secrets_fetch_domain_sid(global_myname, &global_sam_sid)) {
		DOM_SID domain_sid;

		/* We got our sid. If not a pdc/bdc, we're done. */
		if (!is_dc)
			return True;

		if (!secrets_fetch_domain_sid(global_myworkgroup, &domain_sid)) {

			/* No domain sid and we're a pdc/bdc. Store it */

			if (!secrets_store_domain_sid(global_myworkgroup, &global_sam_sid)) {
				DEBUG(0,("pdb_generate_sam_sid: Can't store domain SID as a pdc/bdc.\n"));
				return False;
			}
			return True;
		}

		if (!sid_equal(&domain_sid, &global_sam_sid)) {

			/* Domain name sid doesn't match global sam sid. Re-store global sam sid as domain sid. */

			DEBUG(0,("pdb_generate_sam_sid: Mismatched SIDs as a pdc/bdc.\n"));
			if (!secrets_store_domain_sid(global_myworkgroup, &global_sam_sid)) {
				DEBUG(0,("pdb_generate_sam_sid: Can't re-store domain SID as a pdc/bdc.\n"));
				return False;
			}
			return True;
		}

		return True;
	}

	/* check for an old MACHINE.SID file for backwards compatibility */
	get_private_directory(priv_dir);
	asprintf(&fname, "%s/MACHINE.SID", priv_dir);

	if (read_sid_from_file(fname, &global_sam_sid)) {
		/* remember it for future reference and unlink the old MACHINE.SID */
		if (!secrets_store_domain_sid(global_myname, &global_sam_sid)) {
			DEBUG(0,("pdb_generate_sam_sid: Failed to store SID from file.\n"));
			SAFE_FREE(fname);
			return False;
		}
		unlink(fname);
		if (is_dc) {
			if (!secrets_store_domain_sid(global_myworkgroup, &global_sam_sid)) {
				DEBUG(0,("pdb_generate_sam_sid: Failed to store domain SID from file.\n"));
				SAFE_FREE(fname);
				return False;
			}
		}

		/* Stored the old sid from MACHINE.SID successfully.
			Patch from Stefan "metze" Metzmacher <*****@*****.**>*/
		SAFE_FREE(fname);
		return True;
	}

	SAFE_FREE(fname);

	/* we don't have the SID in secrets.tdb, we will need to
		generate one and save it */
	generate_random_sid(&global_sam_sid);
	DEBUG(10, ("Generated random SID ...\n"));
	if (!secrets_store_domain_sid(global_myname, &global_sam_sid)) {
		DEBUG(0,("pdb_generate_sam_sid: Failed to store generated machine SID.\n"));
		return False;
	}
	if (is_dc) {
		if (!secrets_store_domain_sid(global_myworkgroup, &global_sam_sid)) {
			DEBUG(0,("pdb_generate_sam_sid: Failed to store generated domain SID.\n"));
			return False;
		}
	}

	return True;
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
/*******************************************************************
 Process command line options
 ******************************************************************/
static void process_options(int argc, char **argv, BOOL amroot)
{
	int ch;
	DOM_SID dom_sid;
	fstring sid_str;

	user_name[0] = '\0';

	while ((ch = getopt(argc, argv, "c:axdehmnj:t:r:sw:R:D:U:LSW:X:")) != EOF) {
		switch(ch) {
		case 'L':
			local_mode = amroot = True;
			break;
		case 'c':
			pstrcpy(servicesf,optarg);
			break;
		case 'a':
			if (!amroot) goto bad_args;
			local_flags |= LOCAL_ADD_USER;
			break;
		case 'x':
			if (!amroot) goto bad_args;
			local_flags |= LOCAL_DELETE_USER;
			new_passwd = strdup_x("XXXXXX");
			break;
		case 'd':
			if (!amroot) goto bad_args;
			local_flags |= LOCAL_DISABLE_USER;
			new_passwd = strdup_x("XXXXXX");
			break;
		case 'e':
			if (!amroot) goto bad_args;
			local_flags |= LOCAL_ENABLE_USER;
			break;
		case 'm':
			if (!amroot) goto bad_args;
			local_flags |= LOCAL_TRUST_ACCOUNT;
			break;
		case 'n':
			if (!amroot) goto bad_args;
			local_flags |= LOCAL_SET_NO_PASSWORD;
			new_passwd = strdup_x("NO PASSWORD");
			break;
		case 'j':
			if (!amroot) goto bad_args;
			new_domain = optarg;
			strupper(new_domain);
			joining_domain = True;
			break;
                case 't':
                        if (!amroot) goto bad_args;
                        new_domain = optarg;
                        strupper(new_domain);
			changing_trust_pw = True;
                        break;
		case 'r':
			remote_machine = optarg;
			break;
		case 'S': 
			if (!amroot) goto bad_args;
			local_flags |= LOCAL_GET_DOM_SID;
			break;
		case 's':
			set_line_buffering(stdin);
			set_line_buffering(stdout);
			set_line_buffering(stderr);
			stdin_passwd_get = True;
			break;
		case 'w':
			if (!amroot) goto bad_args;
#ifdef WITH_LDAP_SAM
			local_flags |= LOCAL_SET_LDAP_ADMIN_PW;
			fstrcpy(ldap_secret, optarg);
			break;
#else
			printf("-w not available unless configured --with-ldapsam\n");
			goto bad_args;
#endif			
		case 'R':
			if (!amroot) goto bad_args;
			lp_set_name_resolve_order(optarg);
			break;
		case 'D':
			DEBUGLEVEL = atoi(optarg);
			break;
		case 'U': {
			char *lp;

			got_username = True;
			fstrcpy(user_name, optarg);

			if ((lp = strchr(user_name, '%'))) {
				*lp = 0;
				fstrcpy(user_password, lp + 1);
				got_pass = True;
				memset(strchr(optarg, '%') + 1, 'X',
				       strlen(user_password));
			}

		}
		break;

		case 'W': /* Take the SID on the command line and make it ours */
			if (!lp_load(servicesf,True,False,False)) {
				fprintf(stderr, "Can't load %s - run testparm to debug it\n", 
					servicesf);
				exit(1);
			}

			if (!string_to_sid(&dom_sid, optarg)) {
				fprintf(stderr, "Invalid SID: %s\n", optarg);
				exit(1);
			}
		  	if (!secrets_init()) {
				fprintf(stderr, "Unable to open secrets database!\n");
				exit(1);	
		  	}
			if (!secrets_store_domain_sid(global_myname, &dom_sid)) {
				fprintf(stderr, "Unable to write the new SID %s as the server SID for %s\n", optarg, global_myname);
				exit(1);
			}
			/*
			 * Now, write it to the workgroup as well, to make
			 * things consistent. This is a risk however.
			 */
			if (!secrets_store_domain_sid(lp_workgroup(), &dom_sid)) {
				fprintf(stderr, "Unable to write the new SID %s as the domain SID for %s\n", optarg, lp_workgroup());
				exit(1);
			}

	        	exit(0);	
		break;
	
		case 'X': /* Extract the SID for a domain from secrets */
			if (!lp_load(servicesf,True,False,False)) {
				fprintf(stderr, "Can't load %s - run testparm to debug it\n", 
					servicesf);
				exit(1);
			}
		  if (!secrets_init()) {
			fprintf(stderr, "Unable to open secrets database!\n");
			exit(1);
		  }
		  if (secrets_fetch_domain_sid(optarg, &dom_sid)) {
		    sid_to_string(sid_str, &dom_sid);
		    printf("SID for domain %s is: %s\n", optarg, sid_str);
		    exit(0);
		  }
		  else {
		    fprintf(stderr, "Could not retrieve SID for domain: %s\n", optarg);
		    exit(1);
		  }
		  break;
		case 'h':
		default:
bad_args:
			usage();
		}
	}
	
	argc -= optind;
	argv += optind;

	if (joining_domain && (argc != 0))
		usage();

	switch(argc) {
	case 0:
		if (!got_username)
			fstrcpy(user_name, "");
		break;
	case 1:
		if (!amroot == 1) {
			new_passwd = argv[0];
			break;
		}
		if (got_username)
			usage();
		fstrcpy(user_name, argv[0]);
		break;
	case 2:
		if (!amroot || got_username || got_pass)
			usage();
		fstrcpy(user_name, argv[0]);
		new_passwd = strdup_x(argv[1]);
		break;
	default:
		usage();
	}

}