Beispiel #1
0
ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_principal)
{
	char *password;
	char *new_password;
	ADS_STATUS ret;
	enum netr_SchannelType sec_channel_type;
    
	if ((password = secrets_fetch_machine_password(lp_workgroup(), NULL, &sec_channel_type)) == NULL) {
		DEBUG(1,("Failed to retrieve password for principal %s\n", host_principal));
		return ADS_ERROR_SYSTEM(ENOENT);
	}

	new_password = generate_random_password(talloc_tos(),
				DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH,
				DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);

	ret = kerberos_set_password(ads->auth.kdc_server, host_principal, password, host_principal, new_password, ads->auth.time_offset);

	if (!ADS_ERR_OK(ret)) {
		goto failed;
	}

	if (!secrets_store_machine_password(new_password, lp_workgroup(), sec_channel_type)) {
		DEBUG(1,("Failed to save machine password\n"));
		ret = ADS_ERROR_SYSTEM(EACCES);
		goto failed;
	}

failed:
	SAFE_FREE(password);
	return ret;
}
Beispiel #2
0
bool set_cmdline_auth_info_machine_account_creds(struct user_auth_info *auth_info)
{
	char *pass = NULL;
	char *account = NULL;

	if (!get_cmdline_auth_info_use_machine_account(auth_info)) {
		return false;
	}

	if (!secrets_init()) {
		d_printf("ERROR: Unable to open secrets database\n");
		return false;
	}

	if (asprintf(&account, "%s$@%s", lp_netbios_name(), lp_realm()) < 0) {
		return false;
	}

	pass = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
	if (!pass) {
		d_printf("ERROR: Unable to fetch machine password for "
			"%s in domain %s\n",
			account, lp_workgroup());
		SAFE_FREE(account);
		return false;
	}

	set_cmdline_auth_info_username(auth_info, account);
	set_cmdline_auth_info_password(auth_info, pass);

	SAFE_FREE(account);
	SAFE_FREE(pass);

	return true;
}
Beispiel #3
0
WERROR nt_printer_guid_retrieve(TALLOC_CTX *mem_ctx, const char *printer,
				struct GUID *pguid)
{
	ADS_STRUCT *ads = NULL;
	char *old_krb5ccname = NULL;
	char *printer_dn;
	WERROR result;
	ADS_STATUS ads_status;
	TALLOC_CTX *tmp_ctx;

	tmp_ctx = talloc_new(mem_ctx);
	if (tmp_ctx == NULL) {
		return WERR_NOMEM;
	}

	ads = ads_init(lp_realm(), lp_workgroup(), NULL);
	if (ads == NULL) {
		result = WERR_SERVER_UNAVAILABLE;
		goto out;
	}

	old_krb5ccname = getenv(KRB5_ENV_CCNAME);
	setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
	SAFE_FREE(ads->auth.password);
	ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
							    NULL, NULL);

	ads_status = ads_connect(ads);
	if (!ADS_ERR_OK(ads_status)) {
		DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_status)));
		result = WERR_ACCESS_DENIED;
		goto out;
	}

	result = nt_printer_dn_lookup(tmp_ctx, ads, printer, &printer_dn);
	if (!W_ERROR_IS_OK(result)) {
		goto out;
	}

	result = nt_printer_guid_retrieve_internal(ads, printer_dn, pguid);
out:
	TALLOC_FREE(tmp_ctx);
	ads_destroy(&ads);
	ads_kdestroy("MEMORY:prtpub_cache");
	unsetenv(KRB5_ENV_CCNAME);
	if (old_krb5ccname != NULL) {
		setenv(KRB5_ENV_CCNAME, old_krb5ccname, 0);
	}

	return result;
}
Beispiel #4
0
int net_use_machine_account(void)
{
	char *user_name = NULL;
		
	if (!secrets_init()) {
		d_fprintf(stderr, "ERROR: Unable to open secrets database\n");
		exit(1);
	}

	opt_password = secrets_fetch_machine_password(opt_target_workgroup, NULL, NULL);
	if (asprintf(&user_name, "%s$", global_myname()) == -1) {
		return -1;
	}
	opt_user_name = user_name;
	return 0;
}
Beispiel #5
0
int net_use_krb_machine_account(struct net_context *c)
{
	char *user_name = NULL;

	if (!secrets_init()) {
		d_fprintf(stderr,_("ERROR: Unable to open secrets database\n"));
		exit(1);
	}

	c->opt_password = secrets_fetch_machine_password(
				c->opt_target_workgroup, NULL, NULL);
	if (asprintf(&user_name, "%s$@%s", global_myname(), lp_realm()) == -1) {
		return -1;
	}
	c->opt_user_name = user_name;
	return 0;
}
bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
					  time_t *pass_last_set_time,
					  enum netr_SchannelType *channel)
{
	char *plaintext;

	plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
						   channel);
	if (plaintext) {
		DEBUG(4,("Using cleartext machine password\n"));
		E_md4hash(plaintext, ret_pwd);
		SAFE_FREE(plaintext);
		return True;
	}

	return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
							   pass_last_set_time,
							   channel);
}
Beispiel #7
0
BOOL secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
					  time_t *pass_last_set_time,
					  uint32 *channel)
{
	struct machine_acct_pass *pass;
	char *plaintext;
	size_t size;

	plaintext = secrets_fetch_machine_password(domain, pass_last_set_time, 
						   channel);
	if (plaintext) {
		DEBUG(4,("Using cleartext machine password\n"));
		E_md4hash(plaintext, ret_pwd);
		SAFE_FREE(plaintext);
		return True;
	}

	if (!(pass = secrets_fetch(trust_keystr(domain), &size))) {
		DEBUG(5, ("secrets_fetch failed!\n"));
		return False;
	}
	
	if (size != sizeof(*pass)) {
		DEBUG(0, ("secrets were of incorrect size!\n"));
		return False;
	}

	if (pass_last_set_time) *pass_last_set_time = pass->mod_time;
	memcpy(ret_pwd, pass->hash, 16);
	SAFE_FREE(pass);

	if (channel) 
		*channel = get_default_sec_channel();

	return True;
}
Beispiel #8
0
static NTSTATUS _idmap_adex_init(struct idmap_domain *dom)
{
	ADS_STRUCT *ads = NULL;
	ADS_STATUS status;
	static NTSTATUS init_status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
	struct dom_sid domain_sid;
	fstring dcname;
	struct sockaddr_storage ip;
	struct likewise_cell *lwcell;

	if (NT_STATUS_IS_OK(init_status))
		return NT_STATUS_OK;

	/* Silently fail if we are not a member server in security = ads */

	if ((lp_server_role() != ROLE_DOMAIN_MEMBER) ||
	    (lp_security() != SEC_ADS)) {
		init_status = NT_STATUS_INVALID_SERVER_STATE;
		BAIL_ON_NTSTATUS_ERROR(init_status);
	}

	/* fetch our domain SID first */

	if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
		init_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
		BAIL_ON_NTSTATUS_ERROR(init_status);
	}

	/* reuse the same ticket cache as winbindd */

	setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);

	/* Establish a connection to a DC */

	if ((ads = ads_init(lp_realm(), lp_workgroup(), NULL)) == NULL) {
		init_status = NT_STATUS_NO_MEMORY;
		BAIL_ON_NTSTATUS_ERROR(init_status);
	}

	ads->auth.password =
	    secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
	ads->auth.realm = SMB_STRDUP(lp_realm());

	/* get the DC name here to setup the server affinity cache and
	   local krb5.conf */

	get_dc_name(lp_workgroup(), lp_realm(), dcname, &ip);

	status = ads_connect(ads);
	if (!ADS_ERR_OK(status)) {
		DEBUG(0, ("_idmap_adex_init: ads_connect() failed! (%s)\n",
			  ads_errstr(status)));
	}
	init_status = ads_ntstatus(status);
	BAIL_ON_NTSTATUS_ERROR(init_status);


	/* Find out cell membership */

	init_status = cell_locate_membership(ads);
	if (!NT_STATUS_IS_OK(init_status)) {
		DEBUG(0,("LWI: Fail to locate cell membership (%s).",
			 nt_errstr(init_status)));
		goto done;
	}

	/* Fill in the cell information */

	lwcell = cell_list_head();

	init_status = cell_lookup_settings(lwcell);
	BAIL_ON_NTSTATUS_ERROR(init_status);

	/* Miscellaneous setup.  E.g. set up the list of GC
	   servers and domain list for our forest (does not actually
	   connect). */

	init_status = gc_init_list();
	BAIL_ON_NTSTATUS_ERROR(init_status);

	init_status = domain_init_list();
	BAIL_ON_NTSTATUS_ERROR(init_status);

done:
	if (!NT_STATUS_IS_OK(init_status)) {
		DEBUG(1,("Likewise initialization failed (%s)\n",
			 nt_errstr(init_status)));
	}

	/* cleanup */

	if (!NT_STATUS_IS_OK(init_status)) {
		cell_list_destroy();

		/* init_status stores the failure reason but we need to
		   return success or else idmap_init() will drop us from the
		   backend list */
		return NT_STATUS_OK;
	}

	init_status = NT_STATUS_OK;

	return init_status;
}
Beispiel #9
0
/*
  return our ads connections structure for a domain. We keep the connection
  open to make things faster
*/
static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
{
	ADS_STRUCT *ads;
	ADS_STATUS status;
	fstring dc_name;
	struct sockaddr_storage dc_ss;

	DEBUG(10,("ads_cached_connection\n"));

	if (domain->private_data) {

		time_t expire;
		time_t now = time(NULL);

		/* check for a valid structure */
		ads = (ADS_STRUCT *)domain->private_data;

		expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire);

		DEBUG(7, ("Current tickets expire in %d seconds (at %d, time is now %d)\n",
			  (uint32)expire-(uint32)now, (uint32) expire, (uint32) now));

		if ( ads->config.realm && (expire > now)) {
			return ads;
		} else {
			/* we own this ADS_STRUCT so make sure it goes away */
			DEBUG(7,("Deleting expired krb5 credential cache\n"));
			ads->is_mine = True;
			ads_destroy( &ads );
			ads_kdestroy("MEMORY:winbind_ccache");
			domain->private_data = NULL;
		}
	}

	/* we don't want this to affect the users ccache */
	setenv("KRB5CCNAME", "MEMORY:winbind_ccache", 1);

	ads = ads_init(domain->alt_name, domain->name, NULL);
	if (!ads) {
		DEBUG(1,("ads_init for domain %s failed\n", domain->name));
		return NULL;
	}

	/* the machine acct password might have change - fetch it every time */

	SAFE_FREE(ads->auth.password);
	SAFE_FREE(ads->auth.realm);

	if ( IS_DC ) {

		if ( !pdb_get_trusteddom_pw( domain->name, &ads->auth.password, NULL, NULL ) ) {
			ads_destroy( &ads );
			return NULL;
		}
		ads->auth.realm = SMB_STRDUP( ads->server.realm );
		strupper_m( ads->auth.realm );
	}
	else {
		struct winbindd_domain *our_domain = domain;

		ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);

		/* always give preference to the alt_name in our
		   primary domain if possible */

		if ( !domain->primary )
			our_domain = find_our_domain();

		if ( our_domain->alt_name[0] != '\0' ) {
			ads->auth.realm = SMB_STRDUP( our_domain->alt_name );
			strupper_m( ads->auth.realm );
		}
		else
			ads->auth.realm = SMB_STRDUP( lp_realm() );
	}

	ads->auth.renewable = WINBINDD_PAM_AUTH_KRB5_RENEW_TIME;

	/* Setup the server affinity cache.  We don't reaally care
	   about the name.  Just setup affinity and the KRB5_CONFIG
	   file. */

	get_dc_name( ads->server.workgroup, ads->server.realm, dc_name, &dc_ss );

	status = ads_connect(ads);
	if (!ADS_ERR_OK(status) || !ads->config.realm) {
		DEBUG(1,("ads_connect for domain %s failed: %s\n",
			 domain->name, ads_errstr(status)));
		ads_destroy(&ads);

		/* if we get ECONNREFUSED then it might be a NT4
                   server, fall back to MSRPC */
		if (status.error_type == ENUM_ADS_ERROR_SYSTEM &&
		    status.err.rc == ECONNREFUSED) {
			/* 'reconnect_methods' is the MS-RPC backend. */
			DEBUG(1,("Trying MSRPC methods\n"));
			domain->backend = &reconnect_methods;
		}
		return NULL;
	}

	/* set the flag that says we don't own the memory even
	   though we do so that ads_destroy() won't destroy the
	   structure we pass back by reference */

	ads->is_mine = False;

	domain->private_data = (void *)ads;
	return ads;
}
Beispiel #10
0
 NTSTATUS cell_connect(struct likewise_cell *c)
{
	ADS_STRUCT *ads = NULL;
	ADS_STATUS ads_status;
	fstring dc_name;
	struct sockaddr_storage dcip;
	NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;

	/* have to at least have the AD domain name */

	if (!c->dns_domain) {
		nt_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
		BAIL_ON_NTSTATUS_ERROR(nt_status);
	}

	/* clear out any old information */

	if (c->conn) {
		ads_destroy(&c->conn);
		c->conn = NULL;
	}

	/* now setup the new connection */

	ads = ads_init(c->dns_domain, NULL, NULL);
	BAIL_ON_PTR_ERROR(ads, nt_status);

	ads->auth.password =
	    secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
	ads->auth.realm = SMB_STRDUP(lp_realm());

	/* Make the connection.  We should already have an initial
	   TGT using the machine creds */

	if (cell_flags(c) & LWCELL_FLAG_GC_CELL) {
		ads_status = ads_connect_gc(ads);
	} else {
	  /* Set up server affinity for normal cells and the client
	     site name cache */

	  if (!get_dc_name("", c->dns_domain, dc_name, &dcip)) {
	    nt_status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
	    BAIL_ON_NTSTATUS_ERROR(nt_status);
	  }

	  ads_status = ads_connect(ads);
	}


	c->conn = ads;

	nt_status = ads_ntstatus(ads_status);

done:
	if (!NT_STATUS_IS_OK(nt_status)) {
		ads_destroy(&ads);
		c->conn = NULL;
	}

	return nt_status;
}
Beispiel #11
0
static krb5_error_code ads_secrets_verify_ticket(krb5_context context,
						krb5_auth_context auth_context,
						krb5_principal host_princ,
						const DATA_BLOB *ticket,
						krb5_ticket **pp_tkt,
						krb5_keyblock **keyblock,
						krb5_error_code *perr)
{
	krb5_error_code ret = 0;
	bool auth_ok = False;
	char *password_s = NULL;
	krb5_data password;
	krb5_enctype enctypes[] = { 
#if defined(ENCTYPE_ARCFOUR_HMAC)
		ENCTYPE_ARCFOUR_HMAC,
#endif
		ENCTYPE_DES_CBC_CRC, 
		ENCTYPE_DES_CBC_MD5, 
		ENCTYPE_NULL
	};
	krb5_data packet;
	int i;

	*pp_tkt = NULL;
	*keyblock = NULL;
	*perr = 0;


	if (!secrets_init()) {
		DEBUG(1,("ads_secrets_verify_ticket: secrets_init failed\n"));
		*perr = KRB5_CONFIG_CANTOPEN;
		return False;
	}

	password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
	if (!password_s) {
		DEBUG(1,("ads_secrets_verify_ticket: failed to fetch machine password\n"));
		*perr = KRB5_LIBOS_CANTREADPWD;
		return False;
	}

	password.data = password_s;
	password.length = strlen(password_s);

	/* CIFS doesn't use addresses in tickets. This would break NAT. JRA */

	packet.length = ticket->length;
	packet.data = (char *)ticket->data;

	/* We need to setup a auth context with each possible encoding type in turn. */
	for (i=0;enctypes[i];i++) {
		krb5_keyblock *key = NULL;

		if (!(key = SMB_MALLOC_P(krb5_keyblock))) {
			ret = ENOMEM;
			goto out;
		}
	
		if (create_kerberos_key_from_string(context, host_princ, &password, key, enctypes[i], false)) {
			SAFE_FREE(key);
			continue;
		}

		krb5_auth_con_setuseruserkey(context, auth_context, key);

		if (!(ret = krb5_rd_req(context, &auth_context, &packet, 
					NULL,
					NULL, NULL, pp_tkt))) {
			DEBUG(10,("ads_secrets_verify_ticket: enc type [%u] decrypted message !\n",
				(unsigned int)enctypes[i] ));
			auth_ok = True;
			krb5_copy_keyblock(context, key, keyblock);
			krb5_free_keyblock(context, key);
			break;
		}

		DEBUG((ret != KRB5_BAD_ENCTYPE) ? 3 : 10,
				("ads_secrets_verify_ticket: enc type [%u] failed to decrypt with error %s\n",
				(unsigned int)enctypes[i], error_message(ret)));

		/* successfully decrypted but ticket is just not valid at the moment */
		if (ret == KRB5KRB_AP_ERR_TKT_NYV || 
		    ret == KRB5KRB_AP_ERR_TKT_EXPIRED ||
		    ret == KRB5KRB_AP_ERR_SKEW) {
			krb5_free_keyblock(context, key);
			break;
		}

		krb5_free_keyblock(context, key);

	}

 out:
	SAFE_FREE(password_s);
	*perr = ret;
	return auth_ok;
}
Beispiel #12
0
WERROR check_published_printers(struct messaging_context *msg_ctx)
{
	ADS_STATUS ads_rc;
	ADS_STRUCT *ads = NULL;
	int snum;
	int n_services = lp_numservices();
	TALLOC_CTX *tmp_ctx = NULL;
	struct auth_serversupplied_info *session_info = NULL;
	struct spoolss_PrinterInfo2 *pinfo2;
	NTSTATUS status;
	WERROR result;

	tmp_ctx = talloc_new(NULL);
	if (!tmp_ctx) return WERR_NOMEM;

	ads = ads_init(lp_realm(), lp_workgroup(), NULL);
	if (!ads) {
		DEBUG(3, ("ads_init() failed\n"));
		return WERR_SERVER_UNAVAILABLE;
	}
	setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
	SAFE_FREE(ads->auth.password);
	ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
		NULL, NULL);

	/* ads_connect() will find the DC for us */
	ads_rc = ads_connect(ads);
	if (!ADS_ERR_OK(ads_rc)) {
		DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
		result = WERR_ACCESS_DENIED;
		goto done;
	}

	status = make_session_info_system(tmp_ctx, &session_info);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("check_published_printers: "
			  "Could not create system session_info\n"));
		result = WERR_ACCESS_DENIED;
		goto done;
	}

	for (snum = 0; snum < n_services; snum++) {
		if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
			continue;
		}

		result = winreg_get_printer(tmp_ctx, session_info, msg_ctx,
					    lp_servicename(snum),
					    &pinfo2);
		if (!W_ERROR_IS_OK(result)) {
			continue;
		}

		if (pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
			nt_printer_publish_ads(msg_ctx, ads, pinfo2);
		}

		TALLOC_FREE(pinfo2);
	}

	result = WERR_OK;
done:
	ads_destroy(&ads);
	ads_kdestroy("MEMORY:prtpub_cache");
	talloc_free(tmp_ctx);
	return result;
}
Beispiel #13
0
WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
			  const struct auth_serversupplied_info *session_info,
			  struct messaging_context *msg_ctx,
			  struct spoolss_PrinterInfo2 *pinfo2,
			  int action)
{
	uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ATTRIBUTES;
	struct spoolss_SetPrinterInfo2 *sinfo2;
	ADS_STATUS ads_rc;
	ADS_STRUCT *ads = NULL;
	WERROR win_rc;

	sinfo2 = talloc_zero(mem_ctx, struct spoolss_SetPrinterInfo2);
	if (!sinfo2) {
		return WERR_NOMEM;
	}

	switch (action) {
	case DSPRINT_PUBLISH:
	case DSPRINT_UPDATE:
		pinfo2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
		break;
	case DSPRINT_UNPUBLISH:
		pinfo2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
		break;
	default:
		win_rc = WERR_NOT_SUPPORTED;
		goto done;
	}

	sinfo2->attributes = pinfo2->attributes;

	win_rc = winreg_update_printer(mem_ctx, session_info, msg_ctx,
					pinfo2->sharename, info2_mask,
					sinfo2, NULL, NULL);
	if (!W_ERROR_IS_OK(win_rc)) {
		DEBUG(3, ("err %d saving data\n", W_ERROR_V(win_rc)));
		goto done;
	}

	TALLOC_FREE(sinfo2);

	ads = ads_init(lp_realm(), lp_workgroup(), NULL);
	if (!ads) {
		DEBUG(3, ("ads_init() failed\n"));
		win_rc = WERR_SERVER_UNAVAILABLE;
		goto done;
	}
	setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
	SAFE_FREE(ads->auth.password);
	ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
		NULL, NULL);

	/* ads_connect() will find the DC for us */
	ads_rc = ads_connect(ads);
	if (!ADS_ERR_OK(ads_rc)) {
		DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
		win_rc = WERR_ACCESS_DENIED;
		goto done;
	}

	switch (action) {
	case DSPRINT_PUBLISH:
	case DSPRINT_UPDATE:
		win_rc = nt_printer_publish_ads(msg_ctx, ads, pinfo2);
		break;
	case DSPRINT_UNPUBLISH:
		win_rc = nt_printer_unpublish_ads(ads, pinfo2->sharename);
		break;
	}

done:
	ads_destroy(&ads);
	return win_rc;
}
Beispiel #14
0
static void popt_common_credentials_callback(poptContext con, 
					enum poptCallbackReason reason,
					const struct poptOption *opt,
					const char *arg, const void *data)
{
	char *p;

	if (reason == POPT_CALLBACK_REASON_PRE) {
		cmdline_auth_info.use_kerberos = False;
		cmdline_auth_info.got_pass = False;
		cmdline_auth_info.signing_state = Undefined;
		pstrcpy(cmdline_auth_info.username, "GUEST");	

		if (getenv("LOGNAME"))pstrcpy(cmdline_auth_info.username,getenv("LOGNAME"));

		if (getenv("USER")) {
			pstrcpy(cmdline_auth_info.username,getenv("USER"));

			if ((p = strchr_m(cmdline_auth_info.username,'%'))) {
				*p = 0;
				pstrcpy(cmdline_auth_info.password,p+1);
				cmdline_auth_info.got_pass = True;
				memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(cmdline_auth_info.password));
			}
		}

		if (getenv("PASSWD")) {
			pstrcpy(cmdline_auth_info.password,getenv("PASSWD"));
			cmdline_auth_info.got_pass = True;
		}

		if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) {
			get_password_file(&cmdline_auth_info);
			cmdline_auth_info.got_pass = True;
		}

		return;
	}

	switch(opt->val) {
	case 'U':
		{
			char *lp;

			pstrcpy(cmdline_auth_info.username,arg);
			if ((lp=strchr_m(cmdline_auth_info.username,'%'))) {
				*lp = 0;
				pstrcpy(cmdline_auth_info.password,lp+1);
				cmdline_auth_info.got_pass = True;
				memset(strchr_m(arg,'%')+1,'X',strlen(cmdline_auth_info.password));
			}
		}
		break;

	case 'A':
		get_credentials_file(arg, &cmdline_auth_info);
		break;

	case 'k':
#ifndef HAVE_KRB5
		d_printf("No kerberos support compiled in\n");
		exit(1);
#else
		cmdline_auth_info.use_kerberos = True;
		cmdline_auth_info.got_pass = True;
#endif
		break;

	case 'S':
		{
			cmdline_auth_info.signing_state = -1;
			if (strequal(arg, "off") || strequal(arg, "no") || strequal(arg, "false"))
				cmdline_auth_info.signing_state = False;
			else if (strequal(arg, "on") || strequal(arg, "yes") || strequal(arg, "true") ||
					strequal(arg, "auto") )
				cmdline_auth_info.signing_state = True;
			else if (strequal(arg, "force") || strequal(arg, "required") || strequal(arg, "forced"))
				cmdline_auth_info.signing_state = Required;
			else {
				fprintf(stderr, "Unknown signing option %s\n", arg );
				exit(1);
			}
		}
		break;
	case 'P':
	        {
			char *opt_password = NULL;
			/* it is very useful to be able to make ads queries as the
			   machine account for testing purposes and for domain leave */
			
			if (!secrets_init()) {
				d_printf("ERROR: Unable to open secrets database\n");
				exit(1);
			}
			
			opt_password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
			
			if (!opt_password) {
				d_printf("ERROR: Unable to fetch machine password\n");
				exit(1);
			}
			pstr_sprintf(cmdline_auth_info.username, "%s$", 
				     global_myname());
			pstrcpy(cmdline_auth_info.password,opt_password);
			SAFE_FREE(opt_password);

			/* machine accounts only work with kerberos */
			cmdline_auth_info.use_kerberos = True;
			cmdline_auth_info.got_pass = True;
		}
		break;
	}
}
Beispiel #15
0
static krb5_error_code ads_secrets_verify_ticket(krb5_context context,
						krb5_auth_context auth_context,
						krb5_principal host_princ,
						const DATA_BLOB *ticket,
						krb5_ticket **pp_tkt,
						krb5_keyblock **keyblock,
						krb5_error_code *perr)
{
	krb5_error_code ret = 0;
	bool auth_ok = False;
	bool cont = true;
	char *password_s = NULL;
	/* Let's make some room for 2 password (old and new)*/
	krb5_data passwords[2];
	krb5_enctype enctypes[] = {
#ifdef HAVE_ENCTYPE_AES256_CTS_HMAC_SHA1_96
		ENCTYPE_AES256_CTS_HMAC_SHA1_96,
#endif
#ifdef HAVE_ENCTYPE_AES128_CTS_HMAC_SHA1_96
		ENCTYPE_AES128_CTS_HMAC_SHA1_96,
#endif
		ENCTYPE_ARCFOUR_HMAC,
		ENCTYPE_DES_CBC_CRC,
		ENCTYPE_DES_CBC_MD5,
		ENCTYPE_NULL
	};
	krb5_data packet;
	int i, j;

	*pp_tkt = NULL;
	*keyblock = NULL;
	*perr = 0;

	ZERO_STRUCT(passwords);

	if (!secrets_init()) {
		DEBUG(1,("ads_secrets_verify_ticket: secrets_init failed\n"));
		*perr = KRB5_CONFIG_CANTOPEN;
		return False;
	}

	password_s = secrets_fetch_machine_password(lp_workgroup(),
						    NULL, NULL);
	if (!password_s) {
		DEBUG(1,(__location__ ": failed to fetch machine password\n"));
		*perr = KRB5_LIBOS_CANTREADPWD;
		return False;
	}

	passwords[0].data = password_s;
	passwords[0].length = strlen(password_s);

	password_s = secrets_fetch_prev_machine_password(lp_workgroup());
	if (password_s) {
		DEBUG(10, (__location__ ": found previous password\n"));
		passwords[1].data = password_s;
		passwords[1].length = strlen(password_s);
	}

	/* CIFS doesn't use addresses in tickets. This would break NAT. JRA */

	packet.length = ticket->length;
	packet.data = (char *)ticket->data;

	/* We need to setup a auth context with each possible encoding type
	 * in turn. */
	for (j=0; j<2 && passwords[j].length; j++) {

		for (i=0;enctypes[i];i++) {
			krb5_keyblock *key = NULL;

			if (!(key = SMB_MALLOC_P(krb5_keyblock))) {
				ret = ENOMEM;
				goto out;
			}

			if (create_kerberos_key_from_string(context,
						host_princ, &passwords[j],
						key, enctypes[i], false)) {
				SAFE_FREE(key);
				continue;
			}

			krb5_auth_con_setuseruserkey(context,
							auth_context, key);

			if (!(ret = krb5_rd_req(context, &auth_context,
						&packet, NULL, NULL,
						NULL, pp_tkt))) {
				DEBUG(10, (__location__ ": enc type [%u] "
					   "decrypted message !\n",
					   (unsigned int)enctypes[i]));
				auth_ok = True;
				cont = false;
				krb5_copy_keyblock(context, key, keyblock);
				krb5_free_keyblock(context, key);
				break;
			}

			DEBUG((ret != KRB5_BAD_ENCTYPE) ? 3 : 10,
				(__location__ ": enc type [%u] failed to "
				 "decrypt with error %s\n",
				 (unsigned int)enctypes[i],
				 error_message(ret)));

			/* successfully decrypted but ticket is just not
			 * valid at the moment */
			if (ret == KRB5KRB_AP_ERR_TKT_NYV ||
			    ret == KRB5KRB_AP_ERR_TKT_EXPIRED ||
			    ret == KRB5KRB_AP_ERR_SKEW) {
				krb5_free_keyblock(context, key);
				cont = false;
				break;
			}

			krb5_free_keyblock(context, key);
		}
		if (!cont) {
			/* If we found a valid pass then no need to try
			 * the next one or we have invalid ticket so no need
			 * to try next password*/
			break;
		}
	}

 out:
	SAFE_FREE(passwords[0].data);
	SAFE_FREE(passwords[1].data);
	*perr = ret;
	return auth_ok;
}
Beispiel #16
0
static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
				      const int sockfd,
				      const int pipe_index,
				      const char *controller,
				      struct cli_state **cli,
				      BOOL *retry)
{
	char *machine_password, *machine_krb5_principal;
	char *ipc_username, *ipc_domain, *ipc_password;

	BOOL got_mutex;
	BOOL add_failed_connection = True;

	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;

	struct sockaddr peeraddr;
	socklen_t peeraddr_len;

	struct sockaddr_in *peeraddr_in = (struct sockaddr_in *)&peeraddr;

	machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
							  NULL);
	
	if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
		     lp_realm()) == -1) {
		SAFE_FREE(machine_password);
		return NT_STATUS_NO_MEMORY;
	}

	cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);

	*retry = True;

	got_mutex = secrets_named_mutex(controller,
					WINBIND_SERVER_MUTEX_WAIT_TIME);

	if (!got_mutex) {
		DEBUG(0,("cm_open_connection: mutex grab failed for %s\n",
			 controller));
		result = NT_STATUS_POSSIBLE_DEADLOCK;
		goto done;
	}

	if ((*cli = cli_initialise(NULL)) == NULL) {
		DEBUG(1, ("Could not cli_initialize\n"));
		result = NT_STATUS_NO_MEMORY;
		goto done;
	}

	(*cli)->timeout = 10000; 	/* 10 seconds */
	(*cli)->fd = sockfd;
	fstrcpy((*cli)->desthost, controller);
	(*cli)->use_kerberos = True;

	peeraddr_len = sizeof(peeraddr);

	if ((getpeername((*cli)->fd, &peeraddr, &peeraddr_len) != 0) ||
	    (peeraddr_len != sizeof(struct sockaddr_in)) ||
	    (peeraddr_in->sin_family != PF_INET))
	{
		DEBUG(0,("cm_prepare_connection: %s\n", strerror(errno)));
		goto done;
	}

	if (ntohs(peeraddr_in->sin_port) == 139) {
		struct nmb_name calling;
		struct nmb_name called;

		make_nmb_name(&calling, global_myname(), 0x0);
		make_nmb_name(&called, "*SMBSERVER", 0x20);

		if (!cli_session_request(*cli, &calling, &called)) {
			DEBUG(8, ("cli_session_request failed for %s\n",
				  controller));
			goto done;
		}
	}

	cli_setup_signing_state(*cli, Undefined);

	if (!cli_negprot(*cli)) {
		DEBUG(1, ("cli_negprot failed\n"));
		cli_shutdown(*cli);
		goto done;
	}

	/* Krb5 session */
			
	if ((lp_security() == SEC_ADS) 
	    && ((*cli)->protocol >= PROTOCOL_NT1 &&
		(*cli)->capabilities & CAP_EXTENDED_SECURITY)) {

		ADS_STATUS ads_status;
		(*cli)->use_kerberos = True;
		DEBUG(5, ("connecting to %s from %s with kerberos principal "
			  "[%s]\n", controller, global_myname(),
			  machine_krb5_principal));

		ads_status = cli_session_setup_spnego(*cli,
						      machine_krb5_principal, 
						      machine_password, 
						      lp_workgroup());

		if (!ADS_ERR_OK(ads_status))
			DEBUG(4,("failed kerberos session setup with %s\n",
				 ads_errstr(ads_status)));

		result = ads_ntstatus(ads_status);
	}

	if (NT_STATUS_IS_OK(result))
		goto session_setup_done;

	/* Fall back to non-kerberos session setup */

	(*cli)->use_kerberos = False;

	if ((((*cli)->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) != 0) &&
	    (strlen(ipc_username) > 0)) {

		/* Only try authenticated if we have a username */

		DEBUG(5, ("connecting to %s from %s with username "
			  "[%s]\\[%s]\n",  controller, global_myname(),
			  ipc_domain, ipc_username));

		if (cli_session_setup(*cli, ipc_username,
				      ipc_password, strlen(ipc_password)+1,
				      ipc_password, strlen(ipc_password)+1,
				      ipc_domain)) {
			DEBUG(5, ("authenticated session setup failed\n"));
			goto session_setup_done;
		}
	}

	/* Fall back to anonymous connection, this might fail later */

	if (cli_session_setup(*cli, "", NULL, 0, NULL, 0, "")) {
		DEBUG(5, ("Connected anonymously\n"));
		goto session_setup_done;
	}

	result = cli_nt_error(*cli);

	if (NT_STATUS_IS_OK(result))
		result = NT_STATUS_UNSUCCESSFUL;

	/* We can't session setup */

	goto done;

 session_setup_done:

	if (!cli_send_tconX(*cli, "IPC$", "IPC", "", 0)) {

		result = cli_nt_error(*cli);

		DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));

		if (NT_STATUS_IS_OK(result))
			result = NT_STATUS_UNSUCCESSFUL;

		cli_shutdown(*cli);
		goto done;
	}

	secrets_named_mutex_release(controller);
	got_mutex = False;
	*retry = False;

	/* Windows 2003 SP1 does not lie LsaOpenPolicy() over schannel.
	   Returns RPC_NT_CANNOT_SUPPPORT (0xc0020041) for that call.
	   So just drop it on the lsarpc pipe */

	if ( (domain->primary || IS_DC) && (pipe_index!=PI_LSARPC) ) {
		NTSTATUS status = setup_schannel( *cli, domain->name );
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(3,("schannel refused - continuing without "
				 "schannel (%s)\n", nt_errstr(status)));
		}
	}

	/* set the domain if empty; needed for schannel connections */
	if ( !*(*cli)->domain )
		fstrcpy( (*cli)->domain, domain->name );

	if ( !cli_nt_session_open (*cli, pipe_index) ) {

		result = NT_STATUS_PIPE_NOT_AVAILABLE;

		/* This might be a NT4 DC */
		if ( is_win2k_pipe(pipe_index) )
			add_failed_connection = False;

		cli_shutdown(*cli);
		goto done;
	}

	result = NT_STATUS_OK;
	add_failed_connection = False;

 done:
	if (got_mutex)
		secrets_named_mutex_release(controller);

	SAFE_FREE(machine_password);
	SAFE_FREE(machine_krb5_principal);
	SAFE_FREE(ipc_username);
	SAFE_FREE(ipc_domain);
	SAFE_FREE(ipc_password);

	if (add_failed_connection)
		add_failed_connection_entry(domain->name, controller, result);

	return result;
}