コード例 #1
0
ファイル: auth_util.c プロジェクト: urisimchoni/samba
/*
  on a logon error possibly map the error to success if "map to guest"
  is set approriately
*/
NTSTATUS do_map_to_guest_server_info(TALLOC_CTX *mem_ctx,
				     NTSTATUS status,
				     const char *user,
				     const char *domain,
				     struct auth_serversupplied_info **server_info)
{
	user = user ? user : "";
	domain = domain ? domain : "";

	if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
		if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
		    (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
			DEBUG(3,("No such user %s [%s] - using guest account\n",
				 user, domain));
			return make_server_info_guest(mem_ctx, server_info);
		}
	} else if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
		if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
			DEBUG(3,("Registered username %s for guest access\n",
				user));
			return make_server_info_guest(mem_ctx, server_info);
		}
	}

	return status;
}
コード例 #2
0
ファイル: sesssetup.c プロジェクト: gittestusername/uClinux
/*
  on a logon error possibly map the error to success if "map to guest"
  is set approriately
*/
static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **server_info,
				const char *user, const char *domain)
{
	if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
		if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) || 
		    (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
			DEBUG(3,("No such user %s [%s] - using guest account\n",
				 user, domain));
			status = make_server_info_guest(server_info);
		}
	}

	if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
		if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
			DEBUG(3,("Registered username %s for guest access\n",user));
			status = make_server_info_guest(server_info);
		}
	}

	return status;
}
コード例 #3
0
static NTSTATUS check_guest_security(const struct auth_context *auth_context,
				     void *my_private_data, 
				     TALLOC_CTX *mem_ctx,
				     const auth_usersupplied_info *user_info, 
				     auth_serversupplied_info **server_info)
{
	/* mark this as 'not for me' */
	NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED;

	if (!(user_info->internal_username 
	      && *user_info->internal_username)) {
		nt_status = make_server_info_guest(server_info);
	}

	return nt_status;
}
コード例 #4
0
ファイル: auth_builtin.c プロジェクト: Alexandr-Galko/samba
static NTSTATUS check_guest_security(const struct auth_context *auth_context,
				     void *my_private_data, 
				     TALLOC_CTX *mem_ctx,
				     const struct auth_usersupplied_info *user_info,
				     struct auth_serversupplied_info **server_info)
{
	/* mark this as 'not for me' */
	NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED;

	DEBUG(10, ("Check auth for: [%s]\n", user_info->mapped.account_name));

	if (!(user_info->mapped.account_name
	      && *user_info->mapped.account_name)) {
		nt_status = make_server_info_guest(NULL, server_info);
	}

	return nt_status;
}
コード例 #5
0
ファイル: auth_util.c プロジェクト: nikatshun/asuswrt-merlin
NTSTATUS make_serverinfo_from_username(TALLOC_CTX *mem_ctx,
				       const char *username,
				       bool use_guest_token,
				       bool is_guest,
				       struct auth_serversupplied_info **presult)
{
	struct auth_serversupplied_info *result;
	struct passwd *pwd;
	NTSTATUS status;

	pwd = Get_Pwnam_alloc(talloc_tos(), username);
	if (pwd == NULL) {
		return NT_STATUS_NO_SUCH_USER;
	}

	status = make_server_info_pw(&result, pwd->pw_name, pwd);

	TALLOC_FREE(pwd);

	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	result->nss_token = true;
	result->guest = is_guest;

	if (use_guest_token) {
		status = make_server_info_guest(mem_ctx, &result);
	} else {
		status = create_local_token(result);
	}

	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(result);
		return status;
	}

	*presult = talloc_steal(mem_ctx, result);
	return NT_STATUS_OK;
}
コード例 #6
0
ファイル: rpc_server.c プロジェクト: themiron/asuswrt-merlin
static NTSTATUS auth_anonymous_session_info(TALLOC_CTX *mem_ctx,
        struct auth_session_info_transport **session_info)
{
    struct auth_session_info_transport *i;
    struct auth_serversupplied_info *s;
    struct auth_user_info_dc *u;
    union netr_Validation val;
    NTSTATUS status;

    i = talloc_zero(mem_ctx, struct auth_session_info_transport);
    if (i == NULL) {
        return NT_STATUS_NO_MEMORY;
    }

    status = make_server_info_guest(i, &s);
    if (!NT_STATUS_IS_OK(status)) {
        return status;
    }

    i->security_token = s->security_token;
    i->session_key    = s->user_session_key;

    val.sam3 = s->info3;

    status = make_user_info_dc_netlogon_validation(mem_ctx,
             "",
             3,
             &val,
             &u);
    if (!NT_STATUS_IS_OK(status)) {
        DEBUG(0, ("conversion of info3 into user_info_dc failed!\n"));
        return status;
    }
    i->info = talloc_move(i, &u->info);
    talloc_free(u);

    *session_info = i;

    return NT_STATUS_OK;
}
コード例 #7
0
static NTSTATUS create_connection_server_info(struct smbd_server_connection *sconn,
					      TALLOC_CTX *mem_ctx, int snum,
                                              struct auth_serversupplied_info *vuid_serverinfo,
					      DATA_BLOB password,
                                              struct auth_serversupplied_info **presult)
{
        if (lp_guest_only(snum)) {
                return make_server_info_guest(mem_ctx, presult);
        }

        if (vuid_serverinfo != NULL) {

		struct auth_serversupplied_info *result;

                /*
                 * This is the normal security != share case where we have a
                 * valid vuid from the session setup.                 */

                if (vuid_serverinfo->guest) {
                        if (!lp_guest_ok(snum)) {
                                DEBUG(2, ("guest user (from session setup) "
                                          "not permitted to access this share "
                                          "(%s)\n", lp_servicename(snum)));
                                return NT_STATUS_ACCESS_DENIED;
                        }
                } else {
                        if (!user_ok_token(vuid_serverinfo->unix_name,
					   pdb_get_domain(vuid_serverinfo->sam_account),
                                           vuid_serverinfo->ptok, snum)) {
                                DEBUG(2, ("user '%s' (from session setup) not "
                                          "permitted to access this share "
                                          "(%s)\n",
                                          vuid_serverinfo->unix_name,
                                          lp_servicename(snum)));
                                return NT_STATUS_ACCESS_DENIED;
                        }
                }

                result = copy_serverinfo(mem_ctx, vuid_serverinfo);
		if (result == NULL) {
			return NT_STATUS_NO_MEMORY;
		}

		*presult = result;
		return NT_STATUS_OK;
        }

        if (lp_security() == SEC_SHARE) {

                fstring user;
		bool guest;

                /* add the sharename as a possible user name if we
                   are in share mode security */

                add_session_user(sconn, lp_servicename(snum));

                /* shall we let them in? */

                if (!authorise_login(sconn, snum,user,password,&guest)) {
                        DEBUG( 2, ( "Invalid username/password for [%s]\n",
                                    lp_servicename(snum)) );
			return NT_STATUS_WRONG_PASSWORD;
                }

		return make_serverinfo_from_username(mem_ctx, user, guest,
						     presult);
        }

	DEBUG(0, ("invalid VUID (vuser) but not in security=share\n"));
	return NT_STATUS_ACCESS_DENIED;
}
コード例 #8
0
ファイル: user_krb5.c プロジェクト: eduardok/samba
NTSTATUS make_session_info_krb5(TALLOC_CTX *mem_ctx,
				char *ntuser,
				char *ntdomain,
				char *username,
				struct passwd *pw,
				struct PAC_LOGON_INFO *logon_info,
				bool mapped_to_guest, bool username_was_mapped,
				DATA_BLOB *session_key,
				struct auth_session_info **session_info)
{
	NTSTATUS status;
	struct auth_serversupplied_info *server_info;

	if (mapped_to_guest) {
		status = make_server_info_guest(mem_ctx, &server_info);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(1, ("make_server_info_guest failed: %s!\n",
				  nt_errstr(status)));
			return status;
		}

	} else if (logon_info) {
		/* pass the unmapped username here since map_username()
		   will be called again in make_server_info_info3() */

		status = make_server_info_info3(mem_ctx,
						ntuser, ntdomain,
						&server_info,
						&logon_info->info3);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(1, ("make_server_info_info3 failed: %s!\n",
				  nt_errstr(status)));
			return status;
		}

	} else {
		/*
		 * We didn't get a PAC, we have to make up the user
		 * ourselves. Try to ask the pdb backend to provide
		 * SID consistency with ntlmssp session setup
		 */
		struct samu *sampass;
		/* The stupid make_server_info_XX functions here
		   don't take a talloc context. */
		struct auth_serversupplied_info *tmp = NULL;

		sampass = samu_new(talloc_tos());
		if (sampass == NULL) {
			return NT_STATUS_NO_MEMORY;
		}

		if (pdb_getsampwnam(sampass, username)) {
			DEBUG(10, ("found user %s in passdb, calling "
				   "make_server_info_sam\n", username));
			status = make_server_info_sam(&tmp, sampass);
		} else {
			/*
			 * User not in passdb, make it up artificially
			 */
			DEBUG(10, ("didn't find user %s in passdb, calling "
				   "make_server_info_pw\n", username));
			status = make_server_info_pw(&tmp, username, pw);
		}
		TALLOC_FREE(sampass);

		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(1, ("make_server_info_[sam|pw] failed: %s!\n",
				  nt_errstr(status)));
			return status;
                }

		/* make_server_info_pw does not set the domain. Without this
		 * we end up with the local netbios name in substitutions for
		 * %D. */

		if (server_info->info3 != NULL) {
			server_info->info3->base.domain.string =
				talloc_strdup(server_info->info3, ntdomain);
		}
	}

	server_info->nss_token |= username_was_mapped;

	status = create_local_token(mem_ctx, server_info, session_key, ntuser, session_info);
	talloc_free(server_info);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10,("failed to create local token: %s\n",
			  nt_errstr(status)));
		return status;
	}

	return NT_STATUS_OK;
}
コード例 #9
0
ファイル: auth_util.c プロジェクト: urisimchoni/samba
NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, 
				const char *sent_nt_username,
				const char *domain,
				struct auth_serversupplied_info **server_info,
				const struct netr_SamInfo3 *info3)
{
	static const char zeros[16] = {0, };

	NTSTATUS nt_status = NT_STATUS_OK;
	char *found_username = NULL;
	const char *nt_domain;
	const char *nt_username;
	struct dom_sid user_sid;
	struct dom_sid group_sid;
	bool username_was_mapped;
	struct passwd *pwd;
	struct auth_serversupplied_info *result;
	TALLOC_CTX *tmp_ctx = talloc_stackframe();

	/* 
	   Here is where we should check the list of
	   trusted domains, and verify that the SID 
	   matches.
	*/

	if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) {
		nt_status = NT_STATUS_INVALID_PARAMETER;
		goto out;
	}

	if (!sid_compose(&group_sid, info3->base.domain_sid,
			 info3->base.primary_gid)) {
		nt_status = NT_STATUS_INVALID_PARAMETER;
		goto out;
	}

	nt_username = talloc_strdup(tmp_ctx, info3->base.account_name.string);
	if (!nt_username) {
		/* If the server didn't give us one, just use the one we sent
		 * them */
		nt_username = sent_nt_username;
	}

	nt_domain = talloc_strdup(mem_ctx, info3->base.logon_domain.string);
	if (!nt_domain) {
		/* If the server didn't give us one, just use the one we sent
		 * them */
		nt_domain = domain;
	}

	/* If getpwnam() fails try the add user script (2.2.x behavior).

	   We use the _unmapped_ username here in an attempt to provide
	   consistent username mapping behavior between kerberos and NTLM[SSP]
	   authentication in domain mode security.  I.E. Username mapping
	   should be applied to the fully qualified username
	   (e.g. DOMAIN\user) and not just the login name.  Yes this means we
	   called map_username() unnecessarily in make_user_info_map() but
	   that is how the current code is designed.  Making the change here
	   is the least disruptive place.  -- jerry */

	/* this call will try to create the user if necessary */

	nt_status = check_account(tmp_ctx,
				  nt_domain,
				  nt_username,
				  &found_username,
				  &pwd,
				  &username_was_mapped);

	if (!NT_STATUS_IS_OK(nt_status)) {
		/* Handle 'map to guest = Bad Uid */
		if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) &&
		    (lp_security() == SEC_ADS || lp_security() == SEC_DOMAIN) &&
		    lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID) {
			DBG_NOTICE("Try to map %s to guest account",
				   nt_username);
			nt_status = make_server_info_guest(tmp_ctx, &result);
			if (NT_STATUS_IS_OK(nt_status)) {
				*server_info = talloc_move(mem_ctx, &result);
			}
		}
		goto out;
	}

	result = make_server_info(tmp_ctx);
	if (result == NULL) {
		DEBUG(4, ("make_server_info failed!\n"));
		nt_status = NT_STATUS_NO_MEMORY;
		goto out;
	}

	result->unix_name = talloc_strdup(result, found_username);

	/* copy in the info3 */
	result->info3 = copy_netr_SamInfo3(result, info3);
	if (result->info3 == NULL) {
		nt_status = NT_STATUS_NO_MEMORY;
		goto out;
	}

	/* Fill in the unix info we found on the way */

	result->utok.uid = pwd->pw_uid;
	result->utok.gid = pwd->pw_gid;

	/* ensure we are never given NULL session keys */

	if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
		result->session_key = data_blob_null;
	} else {
		result->session_key = data_blob_talloc(
			result, info3->base.key.key,
			sizeof(info3->base.key.key));
	}

	if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
		result->lm_session_key = data_blob_null;
	} else {
		result->lm_session_key = data_blob_talloc(
			result, info3->base.LMSessKey.key,
			sizeof(info3->base.LMSessKey.key));
	}

	result->nss_token |= username_was_mapped;

	result->guest = (info3->base.user_flags & NETLOGON_GUEST);

	*server_info = talloc_move(mem_ctx, &result);

	nt_status = NT_STATUS_OK;
out:
	talloc_free(tmp_ctx);

	return nt_status;
}
コード例 #10
0
ファイル: sesssetup.c プロジェクト: gittestusername/uClinux
static int reply_spnego_kerberos(connection_struct *conn, 
				 char *inbuf, char *outbuf,
				 int length, int bufsize,
				 DATA_BLOB *secblob,
				 BOOL *p_invalidate_vuid)
{
	TALLOC_CTX *mem_ctx;
	DATA_BLOB ticket;
	char *client, *p, *domain;
	fstring netbios_domain_name;
	struct passwd *pw;
	fstring user;
	int sess_vuid;
	NTSTATUS ret;
	PAC_DATA *pac_data;
	DATA_BLOB ap_rep, ap_rep_wrapped, response;
	auth_serversupplied_info *server_info = NULL;
	DATA_BLOB session_key = data_blob(NULL, 0);
	uint8 tok_id[2];
	DATA_BLOB nullblob = data_blob(NULL, 0);
	fstring real_username;
	BOOL map_domainuser_to_guest = False;
	BOOL username_was_mapped;
	PAC_LOGON_INFO *logon_info = NULL;

	ZERO_STRUCT(ticket);
	ZERO_STRUCT(pac_data);
	ZERO_STRUCT(ap_rep);
	ZERO_STRUCT(ap_rep_wrapped);
	ZERO_STRUCT(response);

	/* Normally we will always invalidate the intermediate vuid. */
	*p_invalidate_vuid = True;

	mem_ctx = talloc_init("reply_spnego_kerberos");
	if (mem_ctx == NULL) {
		return ERROR_NT(nt_status_squash(NT_STATUS_NO_MEMORY));
	}

	if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
		talloc_destroy(mem_ctx);
		return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
	}

	ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket, &client, &pac_data, &ap_rep, &session_key);

	data_blob_free(&ticket);

	if (!NT_STATUS_IS_OK(ret)) {
#if 0
		/* Experiment that failed. See "only happens with a KDC" comment below. */

		if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {

			/*
			 * Windows in this case returns NT_STATUS_MORE_PROCESSING_REQUIRED
			 * with a negTokenTarg blob containing an krb5_error struct ASN1 encoded
			 * containing KRB5KRB_AP_ERR_SKEW. The client then fixes its
			 * clock and continues rather than giving an error. JRA.
			 * -- Looks like this only happens with a KDC. JRA.
			 */

			BOOL ok = make_krb5_skew_error(&ap_rep);
			if (!ok) {
				talloc_destroy(mem_ctx);
				return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
			}
			ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_ERROR);
			response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
			reply_sesssetup_blob(conn, outbuf, response, NT_STATUS_MORE_PROCESSING_REQUIRED);

			/*
			 * In this one case we don't invalidate the intermediate vuid.
			 * as we're expecting the client to re-use it for the next
			 * sessionsetupX packet. JRA.
			 */

			*p_invalidate_vuid = False;

			data_blob_free(&ap_rep);
			data_blob_free(&ap_rep_wrapped);
			data_blob_free(&response);
			talloc_destroy(mem_ctx);
			return -1; /* already replied */
		}
#else
		if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
			ret = NT_STATUS_LOGON_FAILURE;
		}
#endif
		DEBUG(1,("Failed to verify incoming ticket with error %s!\n", nt_errstr(ret)));	
		talloc_destroy(mem_ctx);
		return ERROR_NT(nt_status_squash(ret));
	}

	DEBUG(3,("Ticket name is [%s]\n", client));

	p = strchr_m(client, '@');
	if (!p) {
		DEBUG(3,("Doesn't look like a valid principal\n"));
		data_blob_free(&ap_rep);
		data_blob_free(&session_key);
		SAFE_FREE(client);
		talloc_destroy(mem_ctx);
		return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
	}

	*p = 0;

	/* save the PAC data if we have it */

	if (pac_data) {
		logon_info = get_logon_info_from_pac(pac_data);
		if (logon_info) {
			netsamlogon_cache_store( client, &logon_info->info3 );
		}
	}

	if (!strequal(p+1, lp_realm())) {
		DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
		if (!lp_allow_trusted_domains()) {
			data_blob_free(&ap_rep);
			data_blob_free(&session_key);
			SAFE_FREE(client);
			talloc_destroy(mem_ctx);
			return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
		}
	}

	/* this gives a fully qualified user name (ie. with full realm).
	   that leads to very long usernames, but what else can we do? */

	domain = p+1;

	if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {

		unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1);
		domain = netbios_domain_name;
		DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));

	} else {

		/* If we have winbind running, we can (and must) shorten the
		   username by using the short netbios name. Otherwise we will
		   have inconsistent user names. With Kerberos, we get the
		   fully qualified realm, with ntlmssp we get the short
		   name. And even w2k3 does use ntlmssp if you for example
		   connect to an ip address. */

		struct winbindd_request wb_request;
		struct winbindd_response wb_response;
		NSS_STATUS wb_result;

		ZERO_STRUCT(wb_request);
		ZERO_STRUCT(wb_response);

		DEBUG(10, ("Mapping [%s] to short name\n", domain));

		fstrcpy(wb_request.domain_name, domain);

		wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
					     &wb_request, &wb_response);

		if (wb_result == NSS_STATUS_SUCCESS) {

			fstrcpy(netbios_domain_name,
				wb_response.data.domain_info.name);
			domain = netbios_domain_name;

			DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
		} else {
			DEBUG(3, ("Could not find short name -- winbind "
				  "not running?\n"));
		}
	}

	fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
	
	/* lookup the passwd struct, create a new user if necessary */

	username_was_mapped = map_username( user );

	pw = smb_getpwnam( mem_ctx, user, real_username, True );

	if (pw) {
		/* if a real user check pam account restrictions */
		/* only really perfomed if "obey pam restriction" is true */
		/* do this before an eventual mappign to guest occurs */
		ret = smb_pam_accountcheck(pw->pw_name);
		if (  !NT_STATUS_IS_OK(ret)) {
			DEBUG(1, ("PAM account restriction prevents user login\n"));
			data_blob_free(&ap_rep);
			data_blob_free(&session_key);
			TALLOC_FREE(mem_ctx);
			return ERROR_NT(nt_status_squash(ret));
		}
	}

	if (!pw) {

		/* this was originally the behavior of Samba 2.2, if a user
		   did not have a local uid but has been authenticated, then 
		   map them to a guest account */

		if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){ 
			map_domainuser_to_guest = True;
			fstrcpy(user,lp_guestaccount());
			pw = smb_getpwnam( mem_ctx, user, real_username, True );
		} 

		/* extra sanity check that the guest account is valid */

		if ( !pw ) {
			DEBUG(1,("Username %s is invalid on this system\n", user));
			SAFE_FREE(client);
			data_blob_free(&ap_rep);
			data_blob_free(&session_key);
			TALLOC_FREE(mem_ctx);
			return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
		}
	}

	/* setup the string used by %U */
	
	sub_set_smb_name( real_username );
	reload_services(True);

	if ( map_domainuser_to_guest ) {
		make_server_info_guest(&server_info);
	} else if (logon_info) {
		/* pass the unmapped username here since map_username() 
		   will be called again from inside make_server_info_info3() */
		
		ret = make_server_info_info3(mem_ctx, client, domain, 
					     &server_info, &logon_info->info3);
		if ( !NT_STATUS_IS_OK(ret) ) {
			DEBUG(1,("make_server_info_info3 failed: %s!\n",
				 nt_errstr(ret)));
			SAFE_FREE(client);
			data_blob_free(&ap_rep);
			data_blob_free(&session_key);
			TALLOC_FREE(mem_ctx);
			return ERROR_NT(nt_status_squash(ret));
		}

	} else {
		ret = make_server_info_pw(&server_info, real_username, pw);

		if ( !NT_STATUS_IS_OK(ret) ) {
			DEBUG(1,("make_server_info_pw failed: %s!\n",
				 nt_errstr(ret)));
			SAFE_FREE(client);
			data_blob_free(&ap_rep);
			data_blob_free(&session_key);
			TALLOC_FREE(mem_ctx);
			return ERROR_NT(nt_status_squash(ret));
		}

	        /* make_server_info_pw does not set the domain. Without this
		 * we end up with the local netbios name in substitutions for
		 * %D. */

		if (server_info->sam_account != NULL) {
			pdb_set_domain(server_info->sam_account, domain, PDB_SET);
		}
	}

	server_info->was_mapped |= username_was_mapped;
	
	/* we need to build the token for the user. make_server_info_guest()
	   already does this */
	
	if ( !server_info->ptok ) {
		ret = create_local_token( server_info );
		if ( !NT_STATUS_IS_OK(ret) ) {
			SAFE_FREE(client);
			data_blob_free(&ap_rep);
			data_blob_free(&session_key);
			TALLOC_FREE( mem_ctx );
			TALLOC_FREE( server_info );
			return ERROR_NT(nt_status_squash(ret));
		}
	}

	/* register_vuid keeps the server info */
	/* register_vuid takes ownership of session_key, no need to free after this.
 	   A better interface would copy it.... */
	sess_vuid = register_vuid(server_info, session_key, nullblob, client);

	SAFE_FREE(client);

	if (sess_vuid == UID_FIELD_INVALID ) {
		ret = NT_STATUS_LOGON_FAILURE;
	} else {
		/* current_user_info is changed on new vuid */
		reload_services( True );

		set_message(outbuf,4,0,True);
		SSVAL(outbuf, smb_vwv3, 0);
			
		if (server_info->guest) {
			SSVAL(outbuf,smb_vwv2,1);
		}
		
		SSVAL(outbuf, smb_uid, sess_vuid);

		sessionsetup_start_signing_engine(server_info, inbuf);
	}

        /* wrap that up in a nice GSS-API wrapping */
	if (NT_STATUS_IS_OK(ret)) {
		ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
	} else {
		ap_rep_wrapped = data_blob(NULL, 0);
	}
	response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
	reply_sesssetup_blob(conn, outbuf, response, ret);

	data_blob_free(&ap_rep);
	data_blob_free(&ap_rep_wrapped);
	data_blob_free(&response);
	TALLOC_FREE(mem_ctx);

	return -1; /* already replied */
}