Exemple #1
0
WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
			       struct NetGetJoinInformation *r)
{
	if ((lp_security() == SEC_ADS) && lp_realm()) {
		*r->out.name_buffer = talloc_strdup(ctx, lp_realm());
	} else {
		*r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
	}
	if (!*r->out.name_buffer) {
		return WERR_NOMEM;
	}

	switch (lp_server_role()) {
		case ROLE_DOMAIN_MEMBER:
		case ROLE_DOMAIN_PDC:
		case ROLE_DOMAIN_BDC:
			*r->out.name_type = NetSetupDomainName;
			break;
		case ROLE_STANDALONE:
		default:
			*r->out.name_type = NetSetupWorkgroupName;
			break;
	}

	return WERR_OK;
}
Exemple #2
0
static int net_lookup_kdc(struct net_context *c, int argc, const char **argv)
{
#ifdef HAVE_KRB5
	krb5_error_code rc;
	krb5_context ctx;
	struct ip_service *kdcs;
	const char *realm;
	int num_kdcs = 0;
	int i;
	NTSTATUS status;

	initialize_krb5_error_table();
	rc = krb5_init_context(&ctx);
	if (rc) {
		DEBUG(1,("krb5_init_context failed (%s)\n",
			 error_message(rc)));
		return -1;
	}

	if (argc > 0) {
		realm = argv[0];
	} else if (lp_realm() && *lp_realm()) {
		realm = lp_realm();
	} else {
		char **realms;

		rc = krb5_get_host_realm(ctx, NULL, &realms);
		if (rc) {
			DEBUG(1,("krb5_gethost_realm failed (%s)\n",
				 error_message(rc)));
			return -1;
		}
		realm = (const char *) *realms;
	}

	status = get_kdc_list(realm, NULL, &kdcs, &num_kdcs);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1,("get_kdc_list failed (%s)\n", nt_errstr(status)));
		return -1;
	}

	for (i = 0; i < num_kdcs; i++) {
		char addr[INET6_ADDRSTRLEN];

		print_sockaddr(addr, sizeof(addr), &kdcs[i].ss);

		d_printf("%s:%u\n", addr, kdcs[i].port);
	}

	return 0;
#endif
	DEBUG(1, ("No kerberos support\n"));
	return -1;
}
Exemple #3
0
static int net_lookup_kdc(int argc, const char **argv)
{
#ifdef HAVE_KRB5
	krb5_error_code rc;
	krb5_context ctx;
	struct sockaddr_in *addrs;
	int num_kdcs,i;
	krb5_data realm;
	char **realms;

	rc = krb5_init_context(&ctx);
	if (rc) {
		DEBUG(1,("krb5_init_context failed (%s)\n", 
			 error_message(rc)));
		return -1;
	}

	if (argc>0) {
		realm.data = (krb5_pointer) argv[0];
		realm.length = strlen(argv[0]);
	} else if (lp_realm() && *lp_realm()) {
		realm.data = (krb5_pointer) lp_realm();
		realm.length = strlen(realm.data);
	} else {
		rc = krb5_get_host_realm(ctx, NULL, &realms);
		if (rc) {
			DEBUG(1,("krb5_gethost_realm failed (%s)\n",
				 error_message(rc)));
			return -1;
		}
		realm.data = (krb5_pointer) *realms;
		realm.length = strlen(realm.data);
	}

	rc = krb5_locate_kdc(ctx, &realm, &addrs, &num_kdcs, 0);
	if (rc) {
		DEBUG(1, ("krb5_locate_kdc failed (%s)\n", error_message(rc)));
		return -1;
	}
	for (i=0;i<num_kdcs;i++)
		if (addrs[i].sin_family == AF_INET) 
			d_printf("%s:%hd\n", inet_ntoa(addrs[i].sin_addr),
				 ntohs(addrs[i].sin_port));
	return 0;

#endif	
	DEBUG(1, ("No kerberos support\n"));
	return -1;
}
/*
  initialise a ADS_STRUCT, ready for some ads_ ops
*/
ADS_STRUCT *ads_init(const char *realm, 
		     const char *workgroup,
		     const char *ldap_server)
{
	ADS_STRUCT *ads;
	
	ads = SMB_XMALLOC_P(ADS_STRUCT);
	ZERO_STRUCTP(ads);
	
	ads->server.realm = realm? SMB_STRDUP(realm) : NULL;
	ads->server.workgroup = workgroup ? SMB_STRDUP(workgroup) : NULL;
	ads->server.ldap_server = ldap_server? SMB_STRDUP(ldap_server) : NULL;

	/* we need to know if this is a foreign realm */
	if (realm && *realm && !strequal(lp_realm(), realm)) {
		ads->server.foreign = 1;
	}
	if (workgroup && *workgroup && !strequal(lp_workgroup(), workgroup)) {
		ads->server.foreign = 1;
	}

	/* the caller will own the memory by default */
	ads->is_mine = 1;

	return ads;
}
Exemple #5
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;
}
Exemple #6
0
BOOL get_dc_name(const char *domain, const char *realm, fstring srv_name, struct in_addr *ip_out)
{
	struct in_addr dc_ip;
	BOOL ret;
	BOOL our_domain = False;

	zero_ip(&dc_ip);

	ret = False;
	
	if ( strequal(lp_workgroup(), domain) || strequal(lp_realm(), realm) )
		our_domain = True;
	
	/* always try to obey what the admin specified in smb.conf 
	   (for the local domain) */
	
	if ( (our_domain && lp_security()==SEC_ADS) || realm ) {
		ret = ads_dc_name(domain, realm, &dc_ip, srv_name);
	}

	if (!domain) {
		/* if we have only the realm we can't do anything else */
		return False;
	}
	
	if (!ret) {
		/* fall back on rpc methods if the ADS methods fail */
		ret = rpc_dc_name(domain, srv_name, &dc_ip);
	}
		
	*ip_out = dc_ip;

	return ret;
}
Exemple #7
0
static int net_lookup_pdc(struct net_context *c, int argc, const char **argv)
{
	struct sockaddr_storage ss;
	char *pdc_str = NULL;
	const char *domain;
	char addr[INET6_ADDRSTRLEN];

	if (lp_security() == SEC_ADS) {
		domain = lp_realm();
	} else {
		domain = c->opt_target_workgroup;
	}

	if (argc > 0)
		domain=argv[0];

	/* first get PDC */
	if (!get_pdc_ip(domain, &ss))
		return -1;

	print_sockaddr(addr, sizeof(addr), &ss);
	if (asprintf(&pdc_str, "%s", addr) == -1) {
		return -1;
	}
	d_printf("%s\n", pdc_str);
	SAFE_FREE(pdc_str);
	return 0;
}
Exemple #8
0
krb5_error_code
smb_krb5_init_context_basic(TALLOC_CTX *tmp_ctx,
			    struct tevent_context *ev,
			    struct loadparm_context *lp_ctx,
			    krb5_context *_krb5_context)
{
	krb5_error_code ret;
	char **config_files;
	const char *config_file, *realm;
	krb5_context krb5_ctx;

	initialize_krb5_error_table();

	ret = krb5_init_context(&krb5_ctx);
	if (ret) {
		DEBUG(1,("krb5_init_context failed (%s)\n",
			 error_message(ret)));
		return ret;
	}

	config_file = config_path(tmp_ctx, lp_ctx, "krb5.conf");
	if (!config_file) {
		krb5_free_context(krb5_ctx);
		return ENOMEM;
	}

	/* Use our local krb5.conf file by default */
	ret = krb5_prepend_config_files_default(config_file == NULL?"":config_file, &config_files);
	if (ret) {
		DEBUG(1,("krb5_prepend_config_files_default failed (%s)\n",
			 smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx)));
		krb5_free_context(krb5_ctx);
		return ret;
	}

	ret = krb5_set_config_files(krb5_ctx, config_files);
	krb5_free_config_files(config_files);
	if (ret) {
		DEBUG(1,("krb5_set_config_files failed (%s)\n",
			 smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx)));
		krb5_free_context(krb5_ctx);
		return ret;
	}

	realm = lp_realm(lp_ctx);
	if (realm != NULL) {
		ret = krb5_set_default_realm(krb5_ctx, realm);
		if (ret) {
			DEBUG(1,("krb5_set_default_realm failed (%s)\n",
				 smb_get_krb5_error_message(krb5_ctx, ret, tmp_ctx)));
			krb5_free_context(krb5_ctx);
			return ret;
		}
	}

	*_krb5_context = krb5_ctx;
	return 0;
}
Exemple #9
0
static int negprot_spnego(char *p)
{
    DATA_BLOB blob;
    nstring dos_name;
    fstring unix_name;
    uint8 guid[17];
    const char *OIDs_krb5[] = {OID_KERBEROS5,
                               OID_KERBEROS5_OLD,
                               OID_NTLMSSP,
                               NULL
                              };
    const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
    char *principal;
    int len;

    global_spnego_negotiated = True;

    ZERO_STRUCT(guid);

    safe_strcpy(unix_name, global_myname(), sizeof(unix_name)-1);
    strlower_m(unix_name);
    push_ascii_nstring(dos_name, unix_name);
    safe_strcpy((char *)guid, dos_name, sizeof(guid)-1);

#ifdef DEVELOPER
    /* valgrind fixer... */
    {
        size_t sl = strlen(guid);
        if (sizeof(guid)-sl)
            memset(&guid[sl], '\0', sizeof(guid)-sl);
    }
#endif

#if 0
    /* strangely enough, NT does not sent the single OID NTLMSSP when
       not a ADS member, it sends no OIDs at all

       we can't do this until we teach our sesssion setup parser to know
       about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)
    */
    if (lp_security() != SEC_ADS) {
        memcpy(p, guid, 16);
        return 16;
    }
#endif
    if (lp_security() != SEC_ADS) {
        blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
    } else {
        asprintf(&principal, "%s$@%s", guid, lp_realm());
        blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
        free(principal);
    }
    memcpy(p, blob.data, blob.length);
    len = blob.length;
    data_blob_free(&blob);
    return len;
}
Exemple #10
0
static BOOL make_krb5_skew_error(DATA_BLOB *pblob_out)
{
	krb5_context context = NULL;
	krb5_error_code kerr = 0;
	krb5_data reply;
	krb5_principal host_princ = NULL;
	char *host_princ_s = NULL;
	BOOL ret = False;

	*pblob_out = data_blob(NULL,0);

	initialize_krb5_error_table();
	kerr = krb5_init_context(&context);
	if (kerr) {
		return False;
	}
	/* Create server principal. */
	asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
	if (!host_princ_s) {
		goto out;
	}
	strlower_m(host_princ_s);

	kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
	if (kerr) {
		DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed for name %s: Error %s\n",
			host_princ_s, error_message(kerr) ));
		goto out;
	}
	
	kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW, host_princ, &reply);
	if (kerr) {
		DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error failed: Error %s\n",
			error_message(kerr) ));
		goto out;
	}

	*pblob_out = data_blob(reply.data, reply.length);
	kerberos_free_data_contents(context,&reply);
	ret = True;

  out:

	if (host_princ_s) {
		SAFE_FREE(host_princ_s);
	}
	if (host_princ) {
		krb5_free_principal(context, host_princ);
	}
	krb5_free_context(context);
	return ret;
}
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;
}
Exemple #12
0
static void offer_gss_spnego_mechs(void) {

	DATA_BLOB token;
	SPNEGO_DATA spnego;
	ssize_t len;
	char *reply_base64;

	pstring principal;
	pstring myname_lower;

	ZERO_STRUCT(spnego);

	pstrcpy(myname_lower, global_myname());
	strlower_m(myname_lower);

	pstr_sprintf(principal, "%s$@%s", myname_lower, lp_realm());

	/* Server negTokenInit (mech offerings) */
	spnego.type = SPNEGO_NEG_TOKEN_INIT;
	spnego.negTokenInit.mechTypes = SMB_XMALLOC_ARRAY(const char *, 2);
#ifdef HAVE_KRB5
	spnego.negTokenInit.mechTypes[0] = smb_xstrdup(OID_KERBEROS5_OLD);
	spnego.negTokenInit.mechTypes[1] = smb_xstrdup(OID_NTLMSSP);
	spnego.negTokenInit.mechTypes[2] = NULL;
#else
	spnego.negTokenInit.mechTypes[0] = smb_xstrdup(OID_NTLMSSP);
	spnego.negTokenInit.mechTypes[1] = NULL;
#endif


	spnego.negTokenInit.mechListMIC = data_blob(principal,
						    strlen(principal));

	len = write_spnego_data(&token, &spnego);
	free_spnego_data(&spnego);

	if (len == -1) {
		DEBUG(1, ("Could not write SPNEGO data blob\n"));
		x_fprintf(x_stdout, "BH\n");
		return;
	}

	reply_base64 = base64_encode_data_blob(token);
	x_fprintf(x_stdout, "TT %s *\n", reply_base64);

	SAFE_FREE(reply_base64);
	data_blob_free(&token);
	DEBUG(10, ("sent SPNEGO negTokenInit\n"));
	return;
}
Exemple #13
0
static char *get_user_and_realm(const char *username)
{
	char *user_and_realm = NULL;

	if (!username) {
		return NULL;
	}
	if (strchr_m(username, '@')) {
		user_and_realm = SMB_STRDUP(username);
	} else {
		if (asprintf(&user_and_realm, "%s@%s", username, lp_realm()) == -1) {
			user_and_realm = NULL;
		}
	}
	return user_and_realm;
}
Exemple #14
0
int net_use_krb_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$@%s", global_myname(), lp_realm()) == -1) {
		return -1;
	}
	opt_user_name = user_name;
	return 0;
}
Exemple #15
0
static int net_lookup_dc(struct net_context *c, int argc, const char **argv)
{
	struct ip_service *ip_list;
	struct sockaddr_storage ss;
	char *pdc_str = NULL;
	const char *domain = NULL;
	char *sitename = NULL;
	int count, i;
	char addr[INET6_ADDRSTRLEN];
	bool sec_ads = (lp_security() == SEC_ADS);

	if (sec_ads) {
		domain = lp_realm();
	} else {
		domain = c->opt_target_workgroup;
	}

	if (argc > 0)
		domain=argv[0];

	/* first get PDC */
	if (!get_pdc_ip(domain, &ss))
		return -1;

	print_sockaddr(addr, sizeof(addr), &ss);
	if (asprintf(&pdc_str, "%s", addr) == -1) {
		return -1;
	}
	d_printf("%s\n", pdc_str);

	sitename = sitename_fetch(talloc_tos(), domain);
	if (!NT_STATUS_IS_OK(get_sorted_dc_list(domain, sitename,
					&ip_list, &count, sec_ads))) {
		SAFE_FREE(pdc_str);
		TALLOC_FREE(sitename);
		return 0;
	}
	TALLOC_FREE(sitename);
	for (i=0;i<count;i++) {
		print_sockaddr(addr, sizeof(addr), &ip_list[i].ss);
		if (!strequal(pdc_str, addr))
			d_printf("%s\n", addr);
	}
	SAFE_FREE(pdc_str);
	return 0;
}
static BOOL ads_dc_name(const char *domain, const char *realm, struct in_addr *dc_ip, fstring srv_name)
{
#if 1 /* AR7 */
	return False;
#else 
	ADS_STRUCT *ads;

	if (!realm && strequal(domain, lp_workgroup()))
		realm = lp_realm();

	ads = ads_init(realm, domain, NULL);
	if (!ads)
		return False;

	DEBUG(4,("ads_dc_name: domain=%s\n", domain));

#ifdef HAVE_ADS
	/* we don't need to bind, just connect */
	ads->auth.flags |= ADS_AUTH_NO_BIND;

	ads_connect(ads);
#endif

	if (!ads->config.realm) {
		ads_destroy(&ads);
		return False;
	}

	fstrcpy(srv_name, ads->config.ldap_server_name);
	strupper_m(srv_name);
	*dc_ip = ads->ldap_ip;
	ads_destroy(&ads);
	
	DEBUG(4,("ads_dc_name: using server='%s' IP=%s\n",
		 srv_name, inet_ntoa(*dc_ip)));
	
	return True;
#endif /* AR7 */
}
Exemple #17
0
/*
  initialise a ADS_STRUCT, ready for some ads_ ops
*/
ADS_STRUCT *ads_init(const char *realm, 
		     const char *workgroup,
		     const char *ldap_server)
{
	ADS_STRUCT *ads;
	int wrap_flags;

	ads = SMB_XMALLOC_P(ADS_STRUCT);
	ZERO_STRUCTP(ads);

	ads->server.realm = realm? SMB_STRDUP(realm) : NULL;
	ads->server.workgroup = workgroup ? SMB_STRDUP(workgroup) : NULL;
	ads->server.ldap_server = ldap_server? SMB_STRDUP(ldap_server) : NULL;

	/* we need to know if this is a foreign realm */
	if (realm && *realm && !strequal(lp_realm(), realm)) {
		ads->server.foreign = 1;
	}
	if (workgroup && *workgroup && !strequal(lp_workgroup(), workgroup)) {
		ads->server.foreign = 1;
	}

	/* the caller will own the memory by default */
	ads->is_mine = 1;

	wrap_flags = lp_client_ldap_sasl_wrapping();
	if (wrap_flags == -1) {
		wrap_flags = 0;
	}

	ads->auth.flags = wrap_flags;

	/* Start with a page size of 1000 when the connection is new,
	 * we will drop it by half we get a timeout.   */
	ads->config.ldap_page_size     = 1000;

	return ads;
}
Exemple #18
0
static int net_ads_password(int argc, const char **argv)
{
	ADS_STRUCT *ads;
	const char *auth_principal = opt_user_name;
	const char *auth_password = opt_password;
	char *realm = NULL;
	char *new_password = NULL;
	char *c, *prompt;
	const char *user;
	ADS_STATUS ret;

	if (opt_user_name == NULL || opt_password == NULL) {
		d_printf("You must supply an administrator username/password\n");
		return -1;
	}

	if (argc < 1) {
		d_printf("ERROR: You must say which username to change password for\n");
		return -1;
	}

	user = argv[0];
	if (!strchr_m(user, '@')) {
		asprintf(&c, "%s@%s", argv[0], lp_realm());
		user = c;
	}

	use_in_memory_ccache();    
	c = strchr(auth_principal, '@');
	if (c) {
		realm = ++c;
	} else {
		realm = lp_realm();
	}

	/* use the realm so we can eventually change passwords for users 
	in realms other than default */
	if (!(ads = ads_init(realm, NULL, NULL))) {
		return -1;
	}

	/* we don't actually need a full connect, but it's the easy way to
		fill in the KDC's addresss */
	ads_connect(ads);
    
	if (!ads || !ads->config.realm) {
		d_printf("Didn't find the kerberos server!\n");
		return -1;
	}

	if (argv[1]) {
		new_password = (char *)argv[1];
	} else {
		asprintf(&prompt, "Enter new password for %s:", user);
		new_password = getpass(prompt);
		free(prompt);
	}

	ret = kerberos_set_password(ads->auth.kdc_server, auth_principal, 
				auth_password, user, new_password, ads->auth.time_offset);
	if (!ADS_ERR_OK(ret)) {
		d_printf("Password change failed :-( ...\n");
		ads_destroy(&ads);
		return -1;
	}

	d_printf("Password change for %s completed.\n", user);
	ads_destroy(&ads);

	return 0;
}
Exemple #19
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;
}
Exemple #20
0
static BOOL ads_dc_name(const char *domain,
			const char *realm,
			struct in_addr *dc_ip,
			fstring srv_name)
{
#if 1 /* AVM */
	return False;
#else 
	ADS_STRUCT *ads;
	char *sitename;
	int i;

	if (!realm && strequal(domain, lp_workgroup())) {
		realm = lp_realm();
	}

	sitename = sitename_fetch(realm);

	/* Try this 3 times then give up. */
	for( i =0 ; i < 3; i++) {
		ads = ads_init(realm, domain, NULL);
		if (!ads) {
			SAFE_FREE(sitename);
			return False;
		}

		DEBUG(4,("ads_dc_name: domain=%s\n", domain));

#ifdef HAVE_ADS
		/* we don't need to bind, just connect */
		ads->auth.flags |= ADS_AUTH_NO_BIND;
		ads_connect(ads);
#endif

		if (!ads->config.realm) {
			SAFE_FREE(sitename);
			ads_destroy(&ads);
			return False;
		}

		/* Now we've found a server, see if our sitename
		   has changed. If so, we need to re-do the DNS query
		   to ensure we only find servers in our site. */

		if (stored_sitename_changed(realm, sitename)) {
			SAFE_FREE(sitename);
			sitename = sitename_fetch(realm);
			ads_destroy(&ads);
			/* Ensure we don't cache the DC we just connected to. */
			namecache_delete(realm, 0x1C);
			namecache_delete(domain, 0x1C);
			continue;
		}

#ifdef HAVE_KRB5
		if (is_our_primary_domain(domain) && (ads->config.flags & ADS_KDC)) {
			if (ads_closest_dc(ads)) {
				/* We're going to use this KDC for this realm/domain.
				   If we are using sites, then force the krb5 libs
				   to use this KDC. */

				create_local_private_krb5_conf_for_domain(realm,
									domain,
									sitename,
									ads->ldap_ip);
			} else {
				/* use an off site KDC */
				create_local_private_krb5_conf_for_domain(realm,
									domain,
									NULL,
									ads->ldap_ip);
			}
		}
#endif
		break;
	}

	if (i == 3) {
		DEBUG(1,("ads_dc_name: sitename (now \"%s\") keeps changing ???\n",
			sitename ? sitename : ""));
		SAFE_FREE(sitename);
		return False;
	}

	SAFE_FREE(sitename);

	fstrcpy(srv_name, ads->config.ldap_server_name);
	strupper_m(srv_name);
	*dc_ip = ads->ldap_ip;
	ads_destroy(&ads);
	
	DEBUG(4,("ads_dc_name: using server='%s' IP=%s\n",
		 srv_name, inet_ntoa(*dc_ip)));
	
	return True;
#endif /* AVM */
}
Exemple #21
0
static bool ads_keytab_verify_ticket(krb5_context context,
					krb5_auth_context auth_context,
					const DATA_BLOB *ticket,
					krb5_ticket **pp_tkt,
					krb5_keyblock **keyblock,
					krb5_error_code *perr)
{
	krb5_error_code ret = 0;
	bool auth_ok = False;
	krb5_keytab keytab = NULL;
	krb5_kt_cursor kt_cursor;
	krb5_keytab_entry kt_entry;
	char *valid_princ_formats[7] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
	char *entry_princ_s = NULL;
	fstring my_name, my_fqdn;
	int i;
	int number_matched_principals = 0;
	krb5_data packet;

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

	/* Generate the list of principal names which we expect
	 * clients might want to use for authenticating to the file
	 * service.  We allow name$,{host,cifs}/{name,fqdn,name.REALM}. */

	fstrcpy(my_name, global_myname());

	my_fqdn[0] = '\0';
	name_to_fqdn(my_fqdn, global_myname());

	if (asprintf(&valid_princ_formats[0], "%s$@%s", my_name, lp_realm()) == -1) {
		goto out;
	}
	if (asprintf(&valid_princ_formats[1], "host/%s@%s", my_name, lp_realm()) == -1) {
		goto out;
	}
	if (asprintf(&valid_princ_formats[2], "host/%s@%s", my_fqdn, lp_realm()) == -1) {
		goto out;
	}
	if (asprintf(&valid_princ_formats[3], "host/%s.%s@%s", my_name, lp_realm(), lp_realm()) == -1) {
		goto out;
	}
	if (asprintf(&valid_princ_formats[4], "cifs/%s@%s", my_name, lp_realm()) == -1) {
		goto out;
	}
	if (asprintf(&valid_princ_formats[5], "cifs/%s@%s", my_fqdn, lp_realm()) == -1) {
		goto out;
	}
	if (asprintf(&valid_princ_formats[6], "cifs/%s.%s@%s", my_name, lp_realm(), lp_realm()) == -1) {
		goto out;
	}

	ZERO_STRUCT(kt_entry);
	ZERO_STRUCT(kt_cursor);

	ret = smb_krb5_open_keytab(context, NULL, False, &keytab);
	if (ret) {
		DEBUG(1, ("ads_keytab_verify_ticket: smb_krb5_open_keytab failed (%s)\n", error_message(ret)));
		goto out;
	}

	/* Iterate through the keytab.  For each key, if the principal
	 * name case-insensitively matches one of the allowed formats,
	 * try verifying the ticket using that principal. */

	ret = krb5_kt_start_seq_get(context, keytab, &kt_cursor);
	if (ret) {
		DEBUG(1, ("ads_keytab_verify_ticket: krb5_kt_start_seq_get failed (%s)\n", error_message(ret)));
		goto out;
	}
  
	while (!auth_ok && (krb5_kt_next_entry(context, keytab, &kt_entry, &kt_cursor) == 0)) {
		ret = smb_krb5_unparse_name(context, kt_entry.principal, &entry_princ_s);
		if (ret) {
			DEBUG(1, ("ads_keytab_verify_ticket: smb_krb5_unparse_name failed (%s)\n",
				error_message(ret)));
			goto out;
		}

		for (i = 0; i < ARRAY_SIZE(valid_princ_formats); i++) {

			if (!strequal(entry_princ_s, valid_princ_formats[i])) {
				continue;
			}

			number_matched_principals++;
			packet.length = ticket->length;
			packet.data = (char *)ticket->data;
			*pp_tkt = NULL;

			ret = krb5_rd_req_return_keyblock_from_keytab(context, &auth_context, &packet,
							  	      kt_entry.principal, keytab,
								      NULL, pp_tkt, keyblock);

			if (ret) {
				DEBUG(10,("ads_keytab_verify_ticket: "
					"krb5_rd_req_return_keyblock_from_keytab(%s) failed: %s\n",
					entry_princ_s, error_message(ret)));

				/* workaround for MIT: 
				* as krb5_ktfile_get_entry will explicitly
				* close the krb5_keytab as soon as krb5_rd_req
				* has successfully decrypted the ticket but the
				* ticket is not valid yet (due to clockskew)
				* there is no point in querying more keytab
				* entries - Guenther */
					
				if (ret == KRB5KRB_AP_ERR_TKT_NYV || 
				    ret == KRB5KRB_AP_ERR_TKT_EXPIRED ||
				    ret == KRB5KRB_AP_ERR_SKEW) {
					break;
				}
			} else {
				DEBUG(3,("ads_keytab_verify_ticket: "
					"krb5_rd_req_return_keyblock_from_keytab succeeded for principal %s\n",
					entry_princ_s));
				auth_ok = True;
				break;
			}
		}

		/* Free the name we parsed. */
		SAFE_FREE(entry_princ_s);

		/* Free the entry we just read. */
		smb_krb5_kt_free_entry(context, &kt_entry);
		ZERO_STRUCT(kt_entry);
	}
	krb5_kt_end_seq_get(context, keytab, &kt_cursor);

	ZERO_STRUCT(kt_cursor);

  out:
	
	for (i = 0; i < ARRAY_SIZE(valid_princ_formats); i++) {
		SAFE_FREE(valid_princ_formats[i]);
	}
	
	if (!auth_ok) {
		if (!number_matched_principals) {
			DEBUG(3, ("ads_keytab_verify_ticket: no keytab principals matched expected file service name.\n"));
		} else {
			DEBUG(3, ("ads_keytab_verify_ticket: krb5_rd_req failed for all %d matched keytab principals\n",
				number_matched_principals));
		}
	}

	SAFE_FREE(entry_princ_s);

	{
		krb5_keytab_entry zero_kt_entry;
		ZERO_STRUCT(zero_kt_entry);
		if (memcmp(&zero_kt_entry, &kt_entry, sizeof(krb5_keytab_entry))) {
			smb_krb5_kt_free_entry(context, &kt_entry);
		}
	}

	{
		krb5_kt_cursor zero_csr;
		ZERO_STRUCT(zero_csr);
		if ((memcmp(&kt_cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) && keytab) {
			krb5_kt_end_seq_get(context, keytab, &kt_cursor);
		}
	}

	if (keytab) {
		krb5_kt_close(context, keytab);
	}
	*perr = ret;
	return auth_ok;
}
Exemple #22
0
WERROR _wkssvc_NetrUnjoinDomain2(struct pipes_struct *p,
				 struct wkssvc_NetrUnjoinDomain2 *r)
{
	struct libnet_UnjoinCtx *u = NULL;
	char *cleartext_pwd = NULL;
	char *admin_domain = NULL;
	char *admin_account = NULL;
	WERROR werr;
	struct security_token *token = p->session_info->security_token;

	if (!r->in.account || !r->in.encrypted_password) {
		return WERR_INVALID_PARAM;
	}

	if (!security_token_has_privilege(token, SEC_PRIV_MACHINE_ACCOUNT) &&
	    !nt_token_check_domain_rid(token, DOMAIN_RID_ADMINS) &&
	    !nt_token_check_sid(&global_sid_Builtin_Administrators, token)) {
		DEBUG(5,("_wkssvc_NetrUnjoinDomain2: account doesn't have "
			"sufficient privileges\n"));
		return WERR_ACCESS_DENIED;
	}

	werr = decode_wkssvc_join_password_buffer(
		p->mem_ctx, r->in.encrypted_password,
		&p->session_info->session_key, &cleartext_pwd);
	if (!W_ERROR_IS_OK(werr)) {
		return werr;
	}

	split_domain_user(p->mem_ctx,
			  r->in.account,
			  &admin_domain,
			  &admin_account);

	werr = libnet_init_UnjoinCtx(p->mem_ctx, &u);
	if (!W_ERROR_IS_OK(werr)) {
		return werr;
	}

	u->in.domain_name	= lp_realm();
	u->in.unjoin_flags	= r->in.unjoin_flags |
				  WKSSVC_JOIN_FLAGS_JOIN_TYPE;
	u->in.admin_account	= admin_account;
	u->in.admin_password	= cleartext_pwd;
	u->in.debug		= true;
	u->in.modify_config     = lp_config_backend_is_registry();
	u->in.msg_ctx		= p->msg_ctx;

	become_root();
	werr = libnet_Unjoin(p->mem_ctx, u);
	unbecome_root();

	if (!W_ERROR_IS_OK(werr)) {
		DEBUG(5,("_wkssvc_NetrUnjoinDomain2: libnet_Unjoin failed with: %s\n",
			u->out.error_string ? u->out.error_string :
			win_errstr(werr)));
	}

	TALLOC_FREE(u);
	return werr;
}
Exemple #23
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;
}
Exemple #24
0
/* list all domain groups */
static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
				TALLOC_CTX *mem_ctx,
				uint32 *num_entries, 
				struct wb_acct_info **info)
{
	ADS_STRUCT *ads = NULL;
	const char *attrs[] = {"userPrincipalName", "sAMAccountName",
			       "name", "objectSid", NULL};
	int i, count;
	ADS_STATUS rc;
	LDAPMessage *res = NULL;
	LDAPMessage *msg = NULL;
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
	const char *filter;
	bool enum_dom_local_groups = False;

	*num_entries = 0;

	DEBUG(3,("ads: enum_dom_groups\n"));

	if ( !winbindd_can_contact_domain( domain ) ) {
		DEBUG(10,("enum_dom_groups: No incoming trust for domain %s\n",
			  domain->name));		
		return NT_STATUS_OK;
	}

	/* only grab domain local groups for our domain */
	if ( domain->active_directory && strequal(lp_realm(), domain->alt_name)  ) {
		enum_dom_local_groups = True;
	}

	/* Workaround ADS LDAP bug present in MS W2K3 SP0 and W2K SP4 w/o
	 * rollup-fixes:
	 *
	 * According to Section 5.1(4) of RFC 2251 if a value of a type is it's
	 * default value, it MUST be absent. In case of extensible matching the
	 * "dnattr" boolean defaults to FALSE and so it must be only be present
	 * when set to TRUE. 
	 *
	 * When it is set to FALSE and the OpenLDAP lib (correctly) encodes a
	 * filter using bitwise matching rule then the buggy AD fails to decode
	 * the extensible match. As a workaround set it to TRUE and thereby add
	 * the dnAttributes "dn" field to cope with those older AD versions.
	 * It should not harm and won't put any additional load on the AD since
	 * none of the dn components have a bitmask-attribute.
	 *
	 * Thanks to Ralf Haferkamp for input and testing - Guenther */

	filter = talloc_asprintf(mem_ctx, "(&(objectCategory=group)(&(groupType:dn:%s:=%d)(!(groupType:dn:%s:=%d))))", 
				 ADS_LDAP_MATCHING_RULE_BIT_AND, GROUP_TYPE_SECURITY_ENABLED,
				 ADS_LDAP_MATCHING_RULE_BIT_AND, 
				 enum_dom_local_groups ? GROUP_TYPE_BUILTIN_LOCAL_GROUP : GROUP_TYPE_RESOURCE_GROUP);

	if (filter == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	ads = ads_cached_connection(domain);

	if (!ads) {
		domain->last_status = NT_STATUS_SERVER_DISABLED;
		goto done;
	}

	rc = ads_search_retry(ads, &res, filter, attrs);
	if (!ADS_ERR_OK(rc) || !res) {
		DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc)));
		goto done;
	}

	count = ads_count_replies(ads, res);
	if (count == 0) {
		DEBUG(1,("enum_dom_groups: No groups found\n"));
		goto done;
	}

	(*info) = talloc_zero_array(mem_ctx, struct wb_acct_info, count);
	if (!*info) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	i = 0;

	for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
		char *name, *gecos;
		struct dom_sid sid;
		uint32 rid;

		name = ads_pull_username(ads, mem_ctx, msg);
		gecos = ads_pull_string(ads, mem_ctx, msg, "name");
		if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
			DEBUG(1,("No sid for %s !?\n", name));
			continue;
		}

		if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) {
			DEBUG(1,("No rid for %s !?\n", name));
			continue;
		}

		fstrcpy((*info)[i].acct_name, name);
		fstrcpy((*info)[i].acct_desc, gecos);
		(*info)[i].rid = rid;
		i++;
	}

	(*num_entries) = i;

	status = NT_STATUS_OK;

	DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*num_entries)));

done:
	if (res) 
		ads_msgfree(ads, res);

	return status;
}
Exemple #25
0
static ADS_STRUCT *ads_startup(void)
{
	ADS_STRUCT *ads;
	ADS_STATUS status;
	BOOL need_password = False;
	BOOL second_time = False;
	char *cp;
	
	/* lp_realm() should be handled by a command line param, 
	   However, the join requires that realm be set in smb.conf
	   and compares our realm with the remote server's so this is
	   ok until someone needs more flexibility */
	   
	ads = ads_init(lp_realm(), opt_target_workgroup, opt_host);

	if (!opt_user_name) {
		opt_user_name = "administrator";
	}

	if (opt_user_specified) {
		need_password = True;
	}

retry:
	if (!opt_password && need_password && !opt_machine_pass) {
		char *prompt;
		asprintf(&prompt,"%s's password: "******"name@realm", 
        * extract the realm and convert to upper case.
        * This is only used to establish the connection.
        */
       if ((cp = strchr(ads->auth.user_name, '@'))!=0) {
               *cp++ = '\0';
               ads->auth.realm = smb_xstrdup(cp);
               strupper_m(ads->auth.realm);
       }

	status = ads_connect(ads);

	if (!ADS_ERR_OK(status)) {
		if (!need_password && !second_time) {
			need_password = True;
			second_time = True;
			goto retry;
		} else {
			DEBUG(0,("ads_connect: %s\n", ads_errstr(status)));
			return NULL;
		}
	}
	return ads;
}
Exemple #26
0
static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode, 
				      char *buf, int length) 
{
	static NTLMSSP_STATE *ntlmssp_state = NULL;
	SPNEGO_DATA request, response;
	DATA_BLOB token;
	NTSTATUS status;
	ssize_t len;

	char *user = NULL;
	char *domain = NULL;

	const char *reply_code;
	char       *reply_base64;
	pstring     reply_argument;

	if (strlen(buf) < 2) {
		DEBUG(1, ("SPENGO query [%s] invalid", buf));
		x_fprintf(x_stdout, "BH\n");
		return;
	}

	if (strncmp(buf, "YR", 2) == 0) {
		if (ntlmssp_state)
			ntlmssp_end(&ntlmssp_state);
	} else if (strncmp(buf, "KK", 2) == 0) {
		
	} else {
		DEBUG(1, ("SPENGO query [%s] invalid", buf));
		x_fprintf(x_stdout, "BH\n");
		return;
	}

	if ( (strlen(buf) == 2)) {

		/* no client data, get the negTokenInit offering
                   mechanisms */

		offer_gss_spnego_mechs();
		return;
	}

	/* All subsequent requests have a blob. This might be negTokenInit or negTokenTarg */

	if (strlen(buf) <= 3) {
		DEBUG(1, ("GSS-SPNEGO query [%s] invalid\n", buf));
		x_fprintf(x_stdout, "BH\n");
		return;
	}

	token = base64_decode_data_blob(buf + 3);
	len = read_spnego_data(token, &request);
	data_blob_free(&token);

	if (len == -1) {
		DEBUG(1, ("GSS-SPNEGO query [%s] invalid", buf));
		x_fprintf(x_stdout, "BH\n");
		return;
	}

	if (request.type == SPNEGO_NEG_TOKEN_INIT) {

		/* Second request from Client. This is where the
		   client offers its mechanism to use. */

		if ( (request.negTokenInit.mechTypes == NULL) ||
		     (request.negTokenInit.mechTypes[0] == NULL) ) {
			DEBUG(1, ("Client did not offer any mechanism"));
			x_fprintf(x_stdout, "BH\n");
			return;
		}

		status = NT_STATUS_UNSUCCESSFUL;
		if (strcmp(request.negTokenInit.mechTypes[0], OID_NTLMSSP) == 0) {

			if ( request.negTokenInit.mechToken.data == NULL ) {
				DEBUG(1, ("Client did not provide  NTLMSSP data\n"));
				x_fprintf(x_stdout, "BH\n");
				return;
			}

			if ( ntlmssp_state != NULL ) {
				DEBUG(1, ("Client wants a new NTLMSSP challenge, but "
					  "already got one\n"));
				x_fprintf(x_stdout, "BH\n");
				ntlmssp_end(&ntlmssp_state);
				return;
			}

			if (!NT_STATUS_IS_OK(status = ntlm_auth_start_ntlmssp_server(&ntlmssp_state))) {
				x_fprintf(x_stdout, "BH %s\n", nt_errstr(status));
				return;
			}

			DEBUG(10, ("got NTLMSSP packet:\n"));
			dump_data(10, (const char *)request.negTokenInit.mechToken.data,
				  request.negTokenInit.mechToken.length);

			response.type = SPNEGO_NEG_TOKEN_TARG;
			response.negTokenTarg.supportedMech = SMB_STRDUP(OID_NTLMSSP);
			response.negTokenTarg.mechListMIC = data_blob(NULL, 0);

			status = ntlmssp_update(ntlmssp_state,
						       request.negTokenInit.mechToken,
						       &response.negTokenTarg.responseToken);
		}

#ifdef HAVE_KRB5
		if (strcmp(request.negTokenInit.mechTypes[0], OID_KERBEROS5_OLD) == 0) {

			TALLOC_CTX *mem_ctx = talloc_init("manage_gss_spnego_request");
			char *principal;
			DATA_BLOB ap_rep;
			DATA_BLOB session_key;

			if ( request.negTokenInit.mechToken.data == NULL ) {
				DEBUG(1, ("Client did not provide Kerberos data\n"));
				x_fprintf(x_stdout, "BH\n");
				return;
			}

			response.type = SPNEGO_NEG_TOKEN_TARG;
			response.negTokenTarg.supportedMech = SMB_STRDUP(OID_KERBEROS5_OLD);
			response.negTokenTarg.mechListMIC = data_blob(NULL, 0);
			response.negTokenTarg.responseToken = data_blob(NULL, 0);

			status = ads_verify_ticket(mem_ctx, lp_realm(), 0,
						   &request.negTokenInit.mechToken,
						   &principal, NULL, &ap_rep,
						   &session_key);

			talloc_destroy(mem_ctx);

			/* Now in "principal" we have the name we are
                           authenticated as. */

			if (NT_STATUS_IS_OK(status)) {

				domain = strchr_m(principal, '@');

				if (domain == NULL) {
					DEBUG(1, ("Did not get a valid principal "
						  "from ads_verify_ticket\n"));
					x_fprintf(x_stdout, "BH\n");
					return;
				}

				*domain++ = '\0';
				domain = SMB_STRDUP(domain);
				user = SMB_STRDUP(principal);

				data_blob_free(&ap_rep);

				SAFE_FREE(principal);
			}
		}
#endif

	} else {

		if ( (request.negTokenTarg.supportedMech == NULL) ||
		     ( strcmp(request.negTokenTarg.supportedMech, OID_NTLMSSP) != 0 ) ) {
			/* Kerberos should never send a negTokenTarg, OID_NTLMSSP
			   is the only one we support that sends this stuff */
			DEBUG(1, ("Got a negTokenTarg for something non-NTLMSSP: %s\n",
				  request.negTokenTarg.supportedMech));
			x_fprintf(x_stdout, "BH\n");
			return;
		}

		if (request.negTokenTarg.responseToken.data == NULL) {
			DEBUG(1, ("Got a negTokenTarg without a responseToken!\n"));
			x_fprintf(x_stdout, "BH\n");
			return;
		}

		status = ntlmssp_update(ntlmssp_state,
					       request.negTokenTarg.responseToken,
					       &response.negTokenTarg.responseToken);

		response.type = SPNEGO_NEG_TOKEN_TARG;
		response.negTokenTarg.supportedMech = SMB_STRDUP(OID_NTLMSSP);
		response.negTokenTarg.mechListMIC = data_blob(NULL, 0);

		if (NT_STATUS_IS_OK(status)) {
			user = SMB_STRDUP(ntlmssp_state->user);
			domain = SMB_STRDUP(ntlmssp_state->domain);
			ntlmssp_end(&ntlmssp_state);
		}
	}

	free_spnego_data(&request);

	if (NT_STATUS_IS_OK(status)) {
		response.negTokenTarg.negResult = SPNEGO_ACCEPT_COMPLETED;
		reply_code = "AF";
		pstr_sprintf(reply_argument, "%s\\%s", domain, user);
	} else if (NT_STATUS_EQUAL(status,
				   NT_STATUS_MORE_PROCESSING_REQUIRED)) {
		response.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE;
		reply_code = "TT";
		pstr_sprintf(reply_argument, "*");
	} else {
		response.negTokenTarg.negResult = SPNEGO_REJECT;
		reply_code = "NA";
		pstrcpy(reply_argument, nt_errstr(status));
	}

	SAFE_FREE(user);
	SAFE_FREE(domain);

	len = write_spnego_data(&token, &response);
	free_spnego_data(&response);

	if (len == -1) {
		DEBUG(1, ("Could not write SPNEGO data blob\n"));
		x_fprintf(x_stdout, "BH\n");
		return;
	}

	reply_base64 = base64_encode_data_blob(token);

	x_fprintf(x_stdout, "%s %s %s\n",
		  reply_code, reply_base64, reply_argument);

	SAFE_FREE(reply_base64);
	data_blob_free(&token);

	return;
}
Exemple #27
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;
}
Exemple #28
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;
}
Exemple #29
0
static DATA_BLOB negprot_spnego(void)
{
	DATA_BLOB blob;
	nstring dos_name;
	fstring unix_name;
#ifdef DEVELOPER
	size_t slen;
#endif
	char guid[17];
	const char *OIDs_krb5[] = {OID_KERBEROS5,
				   OID_KERBEROS5_OLD,
				   OID_NTLMSSP,
				   NULL};
	const char *OIDs_plain[] = {OID_NTLMSSP, NULL};

	global_spnego_negotiated = True;

	memset(guid, '\0', sizeof(guid));

	safe_strcpy(unix_name, global_myname(), sizeof(unix_name)-1);
	strlower_m(unix_name);
	push_ascii_nstring(dos_name, unix_name);
	safe_strcpy(guid, dos_name, sizeof(guid)-1);

#ifdef DEVELOPER
	/* Fix valgrind 'uninitialized bytes' issue. */
	slen = strlen(dos_name);
	if (slen < sizeof(guid)) {
		memset(guid+slen, '\0', sizeof(guid) - slen);
	}
#endif

	/* strangely enough, NT does not sent the single OID NTLMSSP when
	   not a ADS member, it sends no OIDs at all

	   OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know
		   about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"

	   Our sessionsetup code now handles raw NTLMSSP connects, so we can go
	   back to doing what W2K3 does here. This is needed to make PocketPC 2003
	   CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
	   for details. JRA.

	*/

	if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) {
#if 0
		/* Code for PocketPC client */
		blob = data_blob(guid, 16);
#else
		/* Code for standalone WXP client */
		blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
#endif
	} else {
		fstring myname;
		char *host_princ_s = NULL;

		const char * lkdc_realm =
			lp_parm_talloc_string(GLOBAL_SECTION_SNUM,
				"com.apple", "lkdc realm", NULL);

		myname[0] = '\0';
		get_mydnsfullname(myname);
		strlower_m(myname);

		/* If we have a LKDC, use it unless there is a managed realm
		 * also configured. The managed realm should have precedence.
		 */
		if (lkdc_realm && (*lp_realm() == '\0' ||
				strcmp(lkdc_realm, lp_realm()) == 0)) {
			asprintf(&host_princ_s,
				"cifs/%s@%s", lkdc_realm, lkdc_realm);
		} else {
			asprintf(&host_princ_s, "cifs/%s@%s",
					myname, lp_realm());
		}

		blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s);

		SAFE_FREE(host_princ_s);
		TALLOC_FREE(lkdc_realm);
	}

	return blob;
}
Exemple #30
0
static WERROR sptr_PrintServerData(struct ntptr_GenericHandle *server,
				   TALLOC_CTX *mem_ctx,
				   const char *value_name,
				   union spoolss_PrinterData *r,
				   enum winreg_Type *type)
{
	struct dcerpc_server_info *server_info = lp_dcerpc_server_info(mem_ctx, server->ntptr->lp_ctx);
	if (strcmp("W3SvcInstalled", value_name) == 0) {
		*type		= REG_DWORD;
		r->value	= 0;
		return WERR_OK;
	} else if (strcmp("BeepEnabled", value_name) == 0) {
		*type		= REG_DWORD;
		r->value	= 0;
		return WERR_OK;
	} else if (strcmp("EventLog", value_name) == 0) {
		*type		= REG_DWORD;
		r->value	= 0;
		return WERR_OK;
	} else if (strcmp("NetPopup", value_name) == 0) {
		*type		= REG_DWORD;
		r->value	= 0;
		return WERR_OK;
	} else if (strcmp("NetPopupToComputer", value_name) == 0) {
		*type		= REG_DWORD;
		r->value	= 0;
		return  WERR_OK;
	} else if (strcmp("MajorVersion", value_name) == 0) {
		*type		= REG_DWORD;
		r->value	= 3;
		return WERR_OK;
	} else if (strcmp("MinorVersion", value_name) == 0) {
		*type		= REG_DWORD;
		r->value	= 0;
		return WERR_OK;
	} else if (strcmp("DefaultSpoolDirectory", value_name) == 0) {
		*type		= REG_SZ;
		r->string	= talloc_strdup(mem_ctx, "C:\\PRINTERS");
		W_ERROR_HAVE_NO_MEMORY(r->string);
		return  WERR_OK;
	} else if (strcmp("Architecture", value_name) == 0) {
		*type		= REG_SZ;
		r->string	= talloc_strdup(mem_ctx, SPOOLSS_ARCHITECTURE_NT_X86);
		W_ERROR_HAVE_NO_MEMORY(r->string);
		return  WERR_OK;
	} else if (strcmp("DsPresent", value_name) == 0) {
		*type		= REG_DWORD;
		r->value	= 1;
		return WERR_OK;
	} else if (strcmp("OSVersion", value_name) == 0) {
		DATA_BLOB blob;
		enum ndr_err_code ndr_err;
		struct spoolss_OSVersion os;

		os.major		= server_info->version_major;
		os.minor		= server_info->version_minor;
		os.build		= server_info->version_build;
		os.extra_string		= "";

		ndr_err = ndr_push_struct_blob(&blob, mem_ctx, lp_iconv_convenience(server->ntptr->lp_ctx), &os, (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
			return WERR_GENERAL_FAILURE;
		}

		*type		= REG_BINARY;
		r->binary	= blob;
		return WERR_OK;
	} else if (strcmp("OSVersionEx", value_name) == 0) {
		DATA_BLOB blob;
		enum ndr_err_code ndr_err;
		struct spoolss_OSVersionEx os_ex;

		os_ex.major		= server_info->version_major;
		os_ex.minor		= server_info->version_minor;
		os_ex.build		= server_info->version_build;
		os_ex.extra_string	= "";
		os_ex.service_pack_major= 0;
		os_ex.service_pack_minor= 0;
		os_ex.suite_mask	= 0;
		os_ex.product_type	= 0;
		os_ex.reserved		= 0;

		ndr_err = ndr_push_struct_blob(&blob, mem_ctx, lp_iconv_convenience(server->ntptr->lp_ctx), &os_ex, (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersionEx);
		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
			return WERR_GENERAL_FAILURE;
		}

		*type		= REG_BINARY;
		r->binary	= blob;
		return WERR_OK;
	} else if (strcmp("DNSMachineName", value_name) == 0) {
		if (!lp_realm(server->ntptr->lp_ctx)) return WERR_INVALID_PARAM;

		*type		= REG_SZ;
		r->string	= talloc_asprintf(mem_ctx, "%s.%s",
						   lp_netbios_name(server->ntptr->lp_ctx),
						   lp_realm(server->ntptr->lp_ctx));
		W_ERROR_HAVE_NO_MEMORY(r->string);
		return WERR_OK;
	}

	return WERR_INVALID_PARAM;
}